我已经遇到过几次这种情况,但我真的不知道为什么会发生这种情况。
我有一个受歧视的工会,例如:
type MStep<'A, 'B> =
| Shuttle of Quotations.Expr<'B> * Quotations.Expr<'B>
工会还有更多内容,但这显示了基本问题。
如果我这样做:
let s1 = Shuttle(<@ l.SomeIntProp @>, <@ r.SomeIntProp @>)
let s2 = Shuttle(<@ l.SomeStrProp @>, <@ r.SomeStrProp @>)
我收到编译器错误:
This expression was expected to have type int, but here has type string
同样,如果我以其他顺序创建它们(先是字符串,然后是 int),我会得到相同的错误,但方向相反。
我可以看到编译器可能根据我的用法推断 'B
,但如果我希望 'B
真正通用怎么办?
根据要求,这里有一个更完整的示例:
type MStep<'A, 'B> =
| Shuttle of Quotations.Expr<'B> * Quotations.Expr<'B>
| Ident of Quotations.Expr<'B>
| Trans of Quotations.Expr<'A> * Quotations.Expr<'B> * ('A -> 'B)
let doMig (f:Table<'A>, t:Table<'B>, s:('A * 'B -> MStep<'C, 'D> list)) =
ignore()
let a = doMig(bpdb.Adjustments, ndb.Adjustments, (fun (l,r) ->
[
Shuttle(<@ l.Id @>, <@ r.Id @>)
Shuttle(<@ l.Name @>, <@ r.Name @>)
]
))
这会产生如上所示的编译器错误。
注意:
bpdb
和 ndb
都是由 SqlDataConnection
类型提供程序提供的数据库上下文。
开放的命名空间是:
open System
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq
open System.Xml
open System.Xml.Linq
open Microsoft.FSharp.Quotations.Patterns
open System.Reflection
open System.Diagnostics
最佳答案
问题很明显:
let t = [ //inserted t to have a concrete variable
Shuttle(<@ l.Id @>, <@ r.Id @>);
Shuttle(<@ l.Name @>, <@ r.Name @>)
]
t
的类型到底是什么? 。第一个元素给出 MStep<_,int> list
第二个给出 MStep<_,string>
这是不同的。
只能将相同类型的元素放入列表中。
关于generics - F# 泛型并不那么通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26906808/