Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow implementing the same interface at different generic instantiations in the same type [ RFC FS-1031 ] #545

Open
0x53A opened this issue Feb 24, 2017 · 3 comments

Comments

@0x53A
Copy link
Contributor

@0x53A 0x53A commented Feb 24, 2017

Note: this is a duplicate, but the original proposal was reduced down to only enable inheritance of such types, not implementation in F#.
I would like to ask you to reconsider fully implementing this feature.

Allow implementing the same interface at different generic instantiations in the same type

I propose we ...

Allow to implement the same interface multiple times with different generic instantiations.

E.g.

type I<'T> =
    abstract member M : unit -> 'T

type T() =
    interface I<int> with
        member x.M = 1
    interface I<bool> with
        member x.M = true

The existing way of approaching this problem in F# is ...

The existing workaround is to create one extra level of inheritance per instantiation.

Pros and Cons

The advantages of making this adjustment to F# are ...

Feature parity with C#.

Reduce surprise for new developers.

Remove boilerplate inheritance chains caused by the workaround.

The disadvantages of making this adjustment to F# are ...

Quoting from UV:

[...] This is partly because of the way interface implementation methods are named in compiled IL (only the prefix "I" is added), and partly because the equivalent object expression form can inculde type unknowns, e.g.

{ interface I<> with ...
interface I<
> with ...

and we don't want to support this kind of inference, and equally don't want a non-orthogonality between object expressions and class definitions. [...]

Extra information

Estimated cost (XS, S, M, L, XL, XXL): As this contains changes to code generation and type inference, this is probably M-L, but I am not familiar enough with the code base.

Related suggestions:

Original SO: http://stackoverflow.com/questions/1464109/implementing-the-same-interface-at-different-generic-instantiations
Original UV: https://fslang.uservoice.com/forums/245727-f-language/suggestions/5663504
Original PR: dotnet/fsharp#18

Affadavit (must be submitted)

Please tick this by placing a cross in the box:

  • [ x ] This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • [ ] I have searched both open and closed suggestions on this site and believe this is not a duplicate (It is a duplicate of the original suggestion)
  • [ x ] This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it. (As I understand it, the previous decision was more for technical reasons, e.g. the naming of interface methods)

Please tick all that apply:

  • [ x ] This is not a breaking change to the F# language design
  • [ x ] I would be willing to help implement and/or test this (Willing yes, capable of implementation probably not. I would love to give it a try If you would be willing to hold my hand)
  • I or my company would be willing to help crowdfund F# Software Foundation members to work on this
@dsyme

This comment has been minimized.

Copy link
Collaborator

@dsyme dsyme commented Mar 1, 2017

@0x53A I agree this should be done, as long as the disadvantages tracked above are taken into account int the implementation

@0x53A

This comment has been minimized.

Copy link
Contributor Author

@0x53A 0x53A commented Apr 16, 2017

@dsyme when looking at how C# implements this, I noticed that apparently, Methods don't need to be named uniquely in IL:

image

image

image

ClassLibrary that is imported with alias=al

namespace Namespace
{
    public class Class
    {
    }
}

Console App:

extern alias al;

namespace Namespace
{
    public class Class
    {
    }
}


namespace ConsoleApp1
{
    public interface IA<T>
    {
        object Get();
    }

    public class MyClass : IA<int>, IA<string>, IA<al.Namespace.Class>, IA<global::Namespace.Class>
    {
        object IA<int>.Get()
        {
            return 1;
        }

        object IA<string>.Get()
        {
            return 2;
        }

        object IA<global::Namespace.Class>.Get()
        {
            return 3;
        }

        object IA<al.Namespace.Class>.Get()
        {
            return 4;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var x = new MyClass();
            System.Console.WriteLine((x as IA<al.Namespace.Class>).Get());
            System.Console.WriteLine((x as IA<global::Namespace.Class>).Get());
            System.Console.ReadLine();
        }
    }
}

So unless fsc itself has issues with duplicated names, it may be as easy as just removing the check.

I will try to create a prototype over the next few days / weeks / months / years =)

@0x53A

This comment has been minimized.

Copy link
Contributor Author

@0x53A 0x53A commented Apr 16, 2017

RFC: under discussion
prototype: In progress

@dsyme dsyme added needs rfc and removed needs rfc labels Dec 1, 2017
@dsyme dsyme changed the title Allow implementing the same interface at different generic instantiations in the same type Allow implementing the same interface at different generic instantiations in the same type [ RFC FS-1031 ] Dec 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.