我不了解嵌套函数的F#类型推理系统。当我使用简单类型之外的类型(如int,string,...
)时,它似乎特别破碎这是一些打印一些反射信息的代码的小例子
let inferenceTest () =
let t = int.GetType()
let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
printfn "%s" <| String.concat ", " methods
这很好用!不需要铸造等。现在假设打印涉及更多,因此我们希望将其分离为嵌套函数
let inferenceTestFailsToCompile () =
let printType t =
let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
printfn "%s" <| String.concat ", " methods
let t = int.GetType()
printType t
这失败了“基于此程序点之前的信息查找不确定类型的对象。可能需要类型注释......”
为什么类型系统的信息突然减少?如果我的printType()
函数与inferenceTestFailsToCompile()
当我改为创建一个以t
作为闭包的lambda时,输入问题就消失了
let inferenceTestLambda () =
let t = int.GetType()
let printType =
let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
printfn "%s" <| String.concat ", " methods
printType
答案 0 :(得分:5)
基本上,从左到右从上到下进行类型推断。有很多例外,但我不会进入它们。
在第一个示例中,推理引擎有足够的信息来正确推断类型。
let inferenceTest () =
let t = int.GetType()
let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
printfn "%s" <| String.concat ", " methods
成了
let inferenceTest () =
let (t : type) = int.GetType()
let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
printfn "%s" <| String.concat ", " methods
成了
let inferenceTest () =
let (t : type) = int.GetType()
let methods = (t.GetMethods() : System.Reflection.MethodInfo []) |> Seq.map(fun m -> m.Name)
printfn "%s" <| String.concat ", " methods
成了
let inferenceTest () =
let (t : type) = int.GetType()
let (methods : seq<string>) = (t.GetMethods() : System.Reflection.MethodInfo []) |> Seq.map(fun m -> m.Name)
printfn "%s" <| String.concat ", " methods
使用|>
帮助了
let methods = Seq.map (fun m -> m.Name) (t.GetMethods())
在第二个例子中,这一行被推断为。
let printType (t : 'a) () =
导致错误
let methods = t.GetMethods() |> Seq.map(fun m -> m.Name)
因为t
的类型是通用的,并且没有提供足够的信息供t.GetMethods()
使用。
要解决这些问题,我使用Visual Studio并将鼠标移到变量上以查看类型。然后,如果我发现一个不正确的类型,我开始添加类型定义。这通常会导致修复错误或揭露我的代码中的错误。
编辑:
这是来自Why is F#'s type inference so fickle?
的Robert Harvey答案的一部分F#使用一次传递编译,以便您只能引用类型或 您之前在文件中定义的函数 当前位于或出现在之前指定的文件中 编译顺序。
我最近问Don Syme有关多个源传递的问题 改进类型推断过程。他的回答是
“是的,可以进行多次通过类型推断。还有 产生一组有限约束的单程变化。
然而,这些方法倾向于提供错误的错误消息而且很差 intellisense会产生一个可视化编辑器。“