Before this gets marked as a duplicate: I'm aware that this question is related to various questions about compilation errors when using unit as a type argument. Some examples:
- Why is
unit
treated differently by the F# type system when used as a generic interface argument? - F# interface inheritance failure due to unit
- Using unit as Type Parameter and overriding methods
These are all running into a problem similar to this one:
type Interface<'a> =
abstract member MyFunc : unit -> 'a
let implementingInstance =
{ new Interface<_> with
member __.MyFunc () = () } // Compiler error!
From what I understand, the code does not compile because a unit-returning function gets compiled with void
return internally, which is an extra feature of the CLI rather than a type.
However! The following seems to satisfy the compiler:
type RecordVersion<'a> =
{ MyFunc : unit -> 'a }
let recordInstance =
{ MyFunc = ignore }
This also works if I replace ignore
with a lambda or a let
-bound module function.
To me, this is just another formulation of the exact same thing. (Though at odds with the F# design guidelines, which suggest to prefer interfaces over function-carrying record types.)
I'm interested in designing APIs whose users specify the behavior and types used. Therefore, I would like to avoid cases where unexpected and confusing compiler errors occur. But I'm not quite sure what to make of this. It looks like F#'s "functional" functions do treat unit as a type.
What are the exact conditions for such spurious errors with unit? Can I avoid them in my API by breaking the design guidelines and using records of functions instead of interfaces? (I wouldn't mind much, but I'm not sure if it solves the problem for good.)