Given the following CRTP type in C#:
public abstract class DataProviderBase<TProvider>
where TProvider : DataProviderBase<TProvider> { }
How would I get its generic type definition in F#?
let typeDef = typedefof<DataProviderBase<_>>
yields the error:
Type constraint mismatch when applying the default type ‘DataProviderBase<‘a>’ for a type inference variable. The resulting type would be infinite when unifying ”a’ and ‘DataProviderBase<‘a>’ Consider adding further type constraints
In C#, it would be:
var typeDef = typeof(DataProviderBase<>);
UPDATE
I found a workaround:
[<AbstractClass>]
type DummyProvider() =
inherit DataProviderBase<DummyProvider>()
let typeDef = typeof<DummyProvider>.BaseType.GetGenericTypeDefinition()
Is there another way to do it, without the extra type?
I think this is actually a very good question. I didn’t find a better workaround for this.
You can slightly simplify your workaround by using
typedefoflike this:TECHNICAL DETAILS
The problem is that F#’s
typedefof<'T>is just an ordinary function that takes a type argument (unliketypeofin C#, which is an operator). In order to call it, you need to give it an actual type and the function will then callGetGenericTypeDefinitionunder the cover.The reason why
typedefof<option<_>>works is that F# specifies a default type as an argument (in this caseobj). In general, F# chooses the less concrete type that matches the constraints. In your case:DataProviderBase<_>will becomeDataProviderBase<DataProviderBase<_>>and so on.Unless you define a new type (as in your workaround), there is no concrete type that could be used as a type argument of
typedefof<...>. In this case, the defaulting mechanism simply doesn’t work…