Mas*_*low 6 f# overload-resolution
特定
[
1,"test2"
3,"test"
]
|> dict
// turn it into keyvaluepair sequence
|> Seq.map id
|> fun x -> x.ToDictionary<_,_,_>((fun x -> x.Key), fun x -> x.Value)
Run Code Online (Sandbox Code Playgroud)
如果我没有明确使用<_,_,_>after ,则无法编译ToDictionary.
Intellisense工作正常,但编译失败并出现错误:基于此程序点之前的信息查找不确定类型的对象
因此,似乎Intellisense知道如何解决方法调用.
这似乎是一个线索
|> fun x -> x.ToDictionary<_,_>((fun x -> x.Key), fun x -> x.Value)
Run Code Online (Sandbox Code Playgroud)
失败了
Type constraint mismatch.
The type 'b -> 'c is not compatible with type IEqualityComparer<'a>
The type 'b -> 'c' is not compatible with the type 'IEqualityComparer<'a>'
(using external F# compiler)
Run Code Online (Sandbox Code Playgroud)
x.ToDictionary((fun x -> x.Key), id)
按预期工作
let vMap (item:KeyValuePair<_,_>) = item.Value
x.ToDictionary((fun x -> x.Key), vMap)
Run Code Online (Sandbox Code Playgroud)
我已经复制了FSI和LinqPad中的行为.
作为Eric Lippert的狂热读者,我真的想知道什么是重载决议,(或者可能来自不同地方的扩展方法)在这里与编译器混淆的冲突?
尽管提前知道类型,但编译器会在采用元素选择器和比较器的重载之间感到困惑。lambda 编译FSharpFunc为 C# 中的标准委托类型(如Actionor )Func,并且从一种类型转换为另一种类型时确实会出现问题。为了使其发挥作用,您可以:
为有问题的 Func 提供类型注释
fun x -> x.ToDictionary((fun pair -> pair.Key), (fun (pair : KeyValuePair<_, _>) -> pair.Value)) //compiles
Run Code Online (Sandbox Code Playgroud)
或将参数命名为提示
fun x -> x.ToDictionary((fun pair -> pair.Key), elementSelector = (fun (pair) -> pair.Value))
Run Code Online (Sandbox Code Playgroud)
或者强制它选择 3 个参数的版本:
x.ToLookup((fun pair -> pair.Key), (fun (pair) -> pair.Value), EqualityComparer.Default)
Run Code Online (Sandbox Code Playgroud)
在旁边
在你的例子中,
let vMap (item:KeyValuePair<_,_>) = item.Value
x.ToDictionary((fun x -> x.Key), vMap)
Run Code Online (Sandbox Code Playgroud)
您将明确需要注释,vMap因为编译器无法在没有另一遍的情况下找出该属性存在的类型。例如,
List.map (fun x -> x.Length) ["one"; "two"] // this fails to compile
Run Code Online (Sandbox Code Playgroud)
这是管道运算符如此有用的原因之一,因为它允许您避免类型注释:
["one"; "two"] |> List.map (fun x -> x.Length) // works
List.map (fun (x:string) -> x.Length) ["one"; "two"] //also works
Run Code Online (Sandbox Code Playgroud)