I'm trying to work with expressions in F# (the System.Linq.Expression kind). Here is a quick example of the problem I am having:
let blah = seq {
yield Expression.New(typedefof<'T>)
yield Expression.Constant(1)
}
What I would like is for blah
to be a seq<Expression>
. However the sequence infers its type by the first yield, which is a NewExpression
. This will cause the second yield to result in a compilation failure because it is a ConstantExpression
. A working solution is to upcast all of the yields:
let blah = seq<Expression> {
yield Expression.New(typedefof<'T>) :> Expression
//or
yield upcast Expression.Constant(1)
}
But that feels unwieldy, having to upcast every single time. I thought flexible types might be a possible solution as well, but I've had trouble with that as well. seq<#Expression>
doesn't seem to work.
Is there a way I can generate a sequence of expressions without having to upcast every single one of them?
As others already mentioned, F# does not usually automatically insert upcasts in your code, so you'll need to add a type annotation and cast or the upcast
keyword - I think the comments already cover all the options.
There are two cases when the compiler does upcasts - one is when passing argument to a function and the other is when you create an array or a list literal. The second can actually be used to simplify your example:
let blah<'T> : Expression list =
[ Expression.New(typedefof<'T>)
Expression.Constant(1) ]
Here, the compiler inserts upcast to Expression
automatically. I suppose your actual use case is more complicated - when you need sequence expressions with yield
, this will not work because then you're writing sequence expresions rather than list literals
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With