我正在尝试使用F#中的表达式(System.Linq.Expression类)。以下是我遇到的问题的一个简单示例:
let blah = seq {
yield Expression.New(typedefof<'T>)
yield Expression.Constant(1)
}
我希望blah
成为seq<Expression>
。然而,序列通过第一个产量推断其类型,即NewExpression
。这将导致第二个yield导致编译失败,因为它是ConstantExpression
。一个有效的解决方案是提高所有收益率:
let blah = seq<Expression> {
yield Expression.New(typedefof<'T>) :> Expression
//or
yield upcast Expression.Constant(1)
}
但是这感觉很笨拙,不得不每次都要升级。我认为灵活类型可能也是一种可能的解决方案,但我也遇到了麻烦。 seq<#Expression>
似乎不起作用。
有没有一种方法可以生成一系列表达式,而不必对它们中的每一个进行上传?
答案 0 :(得分:7)
正如其他人已经提到的,F#通常不会自动在代码中插入向上转换,因此您需要添加类型注释和强制转换或upcast
关键字 - 我认为评论已涵盖所有选项。
编译器进行向上转换时有两种情况 - 一种是将参数传递给函数,另一种是在创建数组或列表文字时。第二个实际上可以用来简化你的例子:
let blah<'T> : Expression list =
[ Expression.New(typedefof<'T>)
Expression.Constant(1) ]
此处,编译器会自动向Expression
插入上传。我想您的实际用例更复杂 - 当您需要使用yield
的序列表达式时,这将无效,因为您正在编写序列表达式而不是列表文字