我试图在F#3.0中编写一个函数,它接受一系列元组并返回一个字典,但我似乎无法使语法正确.目标是传递一系列类型为'K*'V的元组并创建一个Dictionary <'K,'V>.虽然我尝试了各种排列,但我无法让编译器接受我的语法,例如:
CreateDictionary<'K, 'V, 'T when 'K : equality and T : 'K*'V>(s : seq<'T>)
Run Code Online (Sandbox Code Playgroud)
另一方面,该声明被接受:
CreateDictionary<'K, 'V when 'K : equality>(s : seq< Tuple<'K,'V> >)
Run Code Online (Sandbox Code Playgroud)
但是当我尝试通过传递seq <'K*'V>来调用它时,编译器在调用站点上抱怨:
...类型seq与seq类型不兼容> ...
这令人困惑,因为我认为F#元组对应于System.Tuple <>.所以,显然我在这里遗漏了一些东西.
声明接受一系列元组的泛型方法的最佳方法是什么?
您不需要为元组类型定义新的泛型类型:
let CreateDictionary<'K, 'V when 'K : equality>(s : seq<'K*'V>) =
(...)
Run Code Online (Sandbox Code Playgroud)
这很好,因为你只想说参数是一系列键值对,其中键支持相等.您尝试编写的那种约束在某些情况下可能很有用,但不是在这里 - 请尝试以下操作:
let CreateDictionary<'K, 'V, 'T when 'K : equality and 'T :> 'K*'V>(s : seq<'T>) =
(...)
Run Code Online (Sandbox Code Playgroud)
这就是说你想要一个类型值的序列,'T其中'T某些类型继承自'K * 'V(aka Tuple<'K, 'V>).但由于元组类型是密封的,编译器会给出一个错误,说明这个约束没有用.
但它在某些情况下可能很有用 - 你可以编写一个函数,它接受实现序列接口的任何类型:
let CreateDictionary<'K, 'V, 'T when 'K : equality and 'T :> seq<'K*'V>>(s : 'T) =
(...)
Run Code Online (Sandbox Code Playgroud)
通常不需要这样做,因为当它们用作函数参数时,F#会自动将列表,数组等转换为序列,但如果你有一个包含任何集合作为第二个参数的元组,它会很有用.
编辑这是一个示例,显示第一个函数按要求运行:
[<NoEqualityAttribute;NoComparisonAttribute>]
type A() = class end
CreateDictionary [1,"hi"] // Compiles fine
CreateDictionary [A(),"hi"] // Error
Run Code Online (Sandbox Code Playgroud)