Reputation: 8907
I have written some test code to wrap my head around the syntax of generics:
let add_stuff<'T> x y =
printfn "%A" (x + y)
let stuff() =
add_stuff 5.5 2.4
add_stuff 3 4
The 2nd add_stuff
call does not compile. Why is this? Why doesn't the compiler infer the types?
Upvotes: 2
Views: 121
Reputation: 5004
There are 2 issues with the code:
First, the generic type 'T
is not used by any of the parameters. The parameters need to be declared of type 'T
like this:
// val add_stuff: 'T -> 'T -> unit
let add_stuff<'T> (x:'T) (y:'T) =
printfn "%A" (x + y)
This creates a new error message:
The declared type parameter 'T' cannot be used here since the type parameter cannot be resolved at compile time
The issue in this case is the +
operator. It uses Statically Resolved Type Parameters which means your function also needs to use them which basically means it needs to be inlined:
// val add_stuff: ^T -> ^T -> unit
let inline add_stuff (x:^T) (y:^T) =
printfn "%A" (x + y)
Notice the difference in the type signature 'T
is a generic type, it can be resolved at runtime. ^T
is an SRTP, it needs to be resolved at compile time, thus the inline
keyword.
If you had not used the +
operator then you would not need to inline it. Notice the difference between pair_stuff
and add_stuff
:
// val pair_stuff: 'T -> 'W -> unit
let pair_stuff (x:'T) (y:'W) =
printfn "%A" (x , y)
// val add_stuff: ^a -> ^b -> unit
let inline add_stuff x y =
printfn "%A" (x + y)
let stuff() =
add_stuff 5.5 2.4
add_stuff 3 4
pair_stuff 5.5 2.4
pair_stuff 3 4
stuff()
// 7.9
// 7
// (5.5, 2.4)
// (3, 4)
Upvotes: 5
Reputation: 36375
You cannot use Generics for this because they are resolved at runtime and will not vary by inlining.
You need to use Statically Resolved Type Parameters which will be resolved at compile time:
let inline add_stuff (x: ^X) (y: ^Y) =
printfn "%A" (x + y)
Statically resolved type parameters are primarily useful in conjunction with member constraints, which are constraints that allow you to specify that a type argument must have a particular member or members in order to be used. There is no way to create this kind of constraint by using a regular generic type parameter.
Upvotes: 3