Understanding F# inline & statically resolved type parameters: F# casting example
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 tryin开发者_运维问答g 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?
This isn't possible, but it's unrelated to static member constraints. Using normal generic constraints is equally doomed, for the same reason:
// doesn't work
let myUpcast<'a, 'b when 'a :> 'b) (x: 'a) : 'b = unbox (box x)
Basically F# does not allow type constraints involving two different type parameters; they are always constrained to be equal.
See my answer to How to constrain one type parameter by another for more commentary.
精彩评论