In C#, I can implement a generic interface twice on one class, using two different type-parameters:
interface IFoo<T> { void Foo(T x); }
class Bar : IFoo<int>, IFoo<float>
{
public void Foo(int x) { }
public void Foo(float y) { }
}
I would like to do the same thing in F#:
type IFoo<'a> = abstract member Foo : 'a -> unit
type Bar() =
interface IFoo<int> with
[<OverloadID("int")>]
member this.Foo x = ()
interface IFoo<float> with
[<OverloadID("float")>]
member this.Foo x = ()
But it gives a compiler error:
This type implements or inherits the same interface at different generic instantiations
'IFoo<float>'
and'IFoo<int>'
. This is not permitted in this version of F#.
I can't find any discussion of this issue on the web. Is such use frowned upon for some reason? Are there plans to allow this in an upcoming release of F#?
Right now I don't know of plans to allow this.. The feature has been planned and is, at least partially (see comments) implemented in F# 4.0.I think the only reasons its currently disallowed are that it's non-trivial to implement (especially with F# type inference), and it rarely arises in practice (I only recall one customer ever asking about this).
Given an infinite amount of time and resources, I think this would be allowed (I can imagine this being added to a future version of the language), but right now it does not seem like this is a feature worth the effort of supporting. (If you know a strong motivating case, please mail fsbugs@microsoft.com.)
EDIT
As an experiment for the curious, I wrote this C#:
and referenced it from F# (with comments suggesting the results)
so this is what typically happens on this 'boundary' stuff with F# - F# can consume this stuff ok, even if you can't author the same stuff from within the language.
There is a reasonable although not elegant way to do it, create a new type for each interface here is an example of consuming multiple events from an ESB (nSvcBus) which requires that each event corresponds to an implemented interface. The first type below contains the generic 'handler' code, the other types just implement the interface and call to the generic handler