Does anyone know why this fails to compile?
type MyInterface<'input, 'output> =
abstract member MyFun: 'input -> 'output
type MyClass() =
interface MyInterface<string, unit> with
member this.MyFun(input: string) = ()
//fails with error FS0017: The member 'MyFun : string -> unit' does not have the correct type to override the corresponding abstract method.
type MyUnit = MyUnit
type MyClass2() =
//success
interface MyInterface<string, MyUnit> with
member this.MyFun(input: string) = MyUnit
This looks like a nasty corner-case in the F# language, but I’m not sure if it qualifies as a by-design limitation or a bug in the compiler. If it is by design limitation, then the error message should say that (because currently, it doesn’t make much sense).
Anyway, the problem is that the F# compiler doesn’t generate code that actually contains the
unittype in the IL. It replaces it withvoid(when used as a return type) or with empty argument list (when used as a method or function argument).This means that in the
MyClasstype, the compiler decides to compile theMyFunmember as a method that takesstringand returnsvoid(but you cannot usevoidas a generic type argument, so this just doesn’t work). In principle, the compiler could use the actualunittype in this case (because that’s the only way to get it working), but that would probably create other inconsistencies elsewhere.Your trick with creating
MyUnitis, I think, a perfectly fine way to solve the problem. Even the core F# library uses something likeMyUnitin some places of the implementation (in asynchronous workflows) to deal with some limitations ofunit(and the way it is compiled).