This post is mostly targeted F# team, but public debates are welcome.
Since F# source code is public domain, a community can take part in development process. I've already seen here some posts about type class feature. So, IMHO, it would be nice to bring it to F#.
After a couple of weeks rushing into a "type class feature in .NET" problem, I can now propose a way to make it possible. I've started with mapping type classes to OO model of CLR. Here is the result.
As you can see from docs, I've mapped type class to abstract generic class, and type class parameters to generic class parameters. Usage is listed in docs. Implementation uses reflection API.
To use a type class feature, you must access
NTypeClasses.TypeClass<YourTypeClass<arg1, arg2, ...>>.Instance. This is the only object of dynamically generated type derived from
YourTypeClass<arg1, arg2, ...>. For each virtual method in your type class (including get_PropertyName and set_PropertyName methods generated from properties), implementation is searched in arg1, arg2, ... classes and in all classes marked with
NTypeClasses.TypeExtensionAttribute. If one is found, the corresponding method in
YourTypeClass<...> is overriden with single call instruction that passes arguments to implementation method. If method is abstract, such an implementation must exist or you'll get
I've also made a program to check if all type arguments used in type classes have such an abstract methods implemented. This can be called on assembly after successful compilation to check that all type class usages is valid. So it is possible to check types after compilation in any .NET language.
Ok then, it seems I'm not very good in explanation, but I hope you got that.
To be done, integrating to F#
Now I'm willing to bring some syntactic sugar for this feature into F#. Here's an example of what I'm trying to make work:
// defining type class Eq with = and <> operations
type Eq<'a> =
abstract member (=): 'a * 'a -> bool
abstract member (<>): 'a * 'a -> bool
default this.(<>)(a, b) = not(this.(=)(a, b))
// defining generic vector which requires 'a to be from Eq
type Vector3D<'a when Eq<'a>> =
val mutable X: 'a
val mutable Y: 'a
val mutable Z: 'a
static member (=)(Vector3D<'a> a, Vector3D<'a> b) =
// resolving = from Eq, using TypeClass<Eq<'a>>.Instance.(=)
a.X = b.X && a.Y = b.Y && a.Z = b.Z
Problems and things to discuss
The first problem is lack of documentation on how F# compiler works internally. Since its code is pretty large, it seems hard to find right places to insert new code, and what part of existing code could be reused in new code. I've put "when
TypeClassName<args>" support into parser, so that it produces an AST node for this. There are some things to be done: write this constraint into class's info, inherit constraints from type class, fix method and operator resolution so that type class's members can be used, and check that all methods and properties are implemented with type class args with fully instantiated type class. Also, currently, there's a possibility in F# compiler to add a constraint to
typar, but this feature requires single constraint for multiple
typars (though one can always add the same constraint instance for multiple
The second problem is that current F# implementation does not support defining static read-only fields I've used in many cases for
NTypeClasses implementation. So, I can't integrate the code into
FSharp.Core as is.
The third problem is compatibility with other .NET languages. There are some ways: integrate support code into
FSharp.Core and require all other languages to reference it to use type classes, develop
FSharp.Core integration in parallel with
NTypeClasses, and use
NTypeClasses from F# compiler.
"I think this will never be possible in any .NET language" by Brian McNamara