使用序列在F#中向上转换

vcs*_*nes 5 f#

我正在尝试使用F#中的表达式(System.Linq.Expression类).以下是我遇到的问题的一个简单示例:

let blah = seq {
    yield Expression.New(typedefof<'T>)
    yield Expression.Constant(1)
}
Run Code Online (Sandbox Code Playgroud)

我想要的是blah成为一个seq<Expression>.然而,序列通过第一个产量推断其类型,即a NewExpression.这将导致第二个yield导致编译失败,因为它是a ConstantExpression.一个有效的解决方案是提高所有收益率:

let blah = seq<Expression> {
    yield Expression.New(typedefof<'T>) :> Expression
    //or
    yield upcast Expression.Constant(1)
}
Run Code Online (Sandbox Code Playgroud)

但这感觉很笨拙,不得不每次都要升级.我认为灵活类型可能也是一种可能的解决方案,但我也遇到了麻烦.seq<#Expression>似乎不起作用.

有没有一种方法可以生成一系列表达式,而不必将它们中的每一个都向上转换?

Tom*_*cek 7

正如其他人已经提到的,F#通常不会自动在代码中插入向上转换,因此您需要添加类型注释和强制转换或upcast关键字 - 我认为评论已涵盖所有选项.

编译器执行 upcast 时有两种情况- 一种是将参数传递给函数,另一种是在创建数组或列表文字时.第二个实际上可以用来简化你的例子:

let blah<'T> : Expression list = 
  [ Expression.New(typedefof<'T>) 
    Expression.Constant(1) ]
Run Code Online (Sandbox Code Playgroud)

这里,编译器Expression自动插入upcast .我想您的实际用例更复杂 - 当您需要序列表达式时yield,这将无法工作,因为那时您正在编写序列表达而不是列表文字