Is it possible to define a generic extension method in F#?
I was trying to use Rhino Mocks with F# code, and the following code was a problematic:
let service = MockRepository.Gen开发者_如何学运维erateMock<IMyService>()
service.Stub(s => s.Name).Return("Service");
This was no surprise, since Stub is not part of IMyService interface, it's a C# extension method that Rhino Mocks defines.
Slighltly modified code works:
let service = MockRepository.GenerateMock<IMyService>()
RhinoMocksExtensions.Stub<IMyService, string>(service, fun s -> s.Name).Return("Service");
However, it would be nice to define an extension method in F#, but then it will be a parameterized generic extension method that would take a tuple . I was trying varios syntax but without any luck. I didn't find information whether this is currently supported in F# or not. If anyone knows, please let me know.
As kvb mentioned, it's not possible in F# 2.0. In this particular case I'd wrap Rhino.Mocks fluent interface to make it more idiomatic in F#, e.g.:
let mstub f target =
RhinoMocksExtensions.Stub(target, Function(f))
let mreturn value (options: IMethodOptions<'a>) =
options.Return value
let service = MockRepository.GenerateMock<IComparer>()
service |> mstub (fun s -> s.Compare(1,2)) |> mreturn 1 |> ignore
What's fluent in one language is not necessarily fluent in another. (sorry for the plug but I really think it's relevant here)
If I understand your question correctly, the answer is no. Section 8.12.1 of the spec (Imported C# Extensions Members) includes this text:
C#-defined extension members are made available to F# code in environments where the C#-authored assembly is referenced and an open declaration of the corresponding namespace is in effect. However, some limitations apply, notably
C# extension members whose “this” parameter is a variable type are not made available to F# code in this version of F#
C# extension members whose “this” parameter is an array type are not made available to F# code in this version of F#
This explains why some extension methods from C# will work (e.g. those in System.Linq), while the one that you are attempting to use will not.
Furthermore, native F# extension methods can only be defined as if they were placed on actual type definitions. In particular, you can't define an F# extension method on a closed generic type (e.g. IEnumerable<string>
) nor can you define an extension method on a generic type variable.
精彩评论