开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜