F#'s inline functions with statically resolved generic parameters seem to be similar to C++'s templates. However, unlike C++, you need to specify the constraints - how does that work?
For example, I'm trying to implement an upcasting function, but this won't work:
let inline myUpcast< ^a, ^b when ^a :> ^b > (x: ^a) : ^b = x
The error message is: error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution.
I'm actually trying to write a function that will cast sequences when the underlying types can be cast (to work around lack of covariance), but the following doesn't quite work either:
let inline upcastseq (xs: seq< ^a >) : seq< ^b > when ^a :> ^b = xs :?> seq< ^b >
which causes the following warning: warning FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type ' ^b'. As might be expected then, actually using the function doesn't work as hoped.
So, I'm looking for a function that will cause a type-check error if used to convert sequences in a covariantly invalid fashion (hence the generic parameter restriction) - is such a thing possible?
A little more generally, what are the limitations of statically resolved type parameters as compared to C++'s templates?