9

在Don Syme、Adam Granicz 和 Antonio Cisternino 撰写的Expert F# 2.0中,第 4 页。44

类型推断:使用 |> 运算符可以让类型信息从输入对象流向操作这些对象的函数。F# 使用从类型推断中收集的信息来解决某些语言结构,例如属性访问和方法重载。这依赖于在整个程序文本中从左到右传播的信息。特别是,在解决属性访问和重载时,不会考虑位置右侧的类型信息。

很明显,使用 |> 可以帮助类型推断。

与往常一样,声明类型也很有帮助。

是否有任何其他方法/策略可用于帮助 F# 类型推断?

编辑

正如 RamonSnir 正确指出的那样,应该让类型推断做尽可能多的工作。因此,仅仅因为你可以添加类型声明并不是一个人应该做的。不要把这个问题或答案当作应该做的事情。我问这个问题是为了帮助更好地理解类型推断的细微差别,以及在类型推断需要帮助的情况下有什么帮助。因此,如果类型推断可以在没有帮助的情况下解析所有类型,那么不要给它任何帮助,但是当它这样做时,知道一些帮助它的方法会很好。

4

1 回答 1

14

几点:

1)更喜欢模块功能而不是属性和方法。

List.map (fun x -> x.Length) ["hello"; "world"] // fails
List.map String.length ["hello"; "world"] // works

let mapFirst xss = Array.map (fun xs -> xs.[0]) xss // fails
let mapFirst xss = Array.map (fun xs -> Array.get xs 0) xss // works

2)更喜欢没有重载的方法。例如,QuickLinq Helpers定义非重载成员以避免 LINQ 扩展方法中的一堆类型注释。

3) 利用任何可用信息给类型检查器一些提示。

let makeStreamReader x = new System.IO.StreamReader(x) // fails
let makeStreamReader x = new System.IO.StreamReader(path=x) // works

最后一个例子取自一篇关于F# 类型推断的优秀文章。

总而言之,您通常不需要帮助 F# 类型检查器。如果存在类型错误,上面链接的摘要提供了一个很好的修复指南:

总而言之,如果编译器抱怨缺少类型或信息不足,您可以做的事情是:

  • 在使用之前定义事物(这包括确保以正确的顺序编译文件)
  • 将具有“已知类型”的事物放在比具有“未知类型”的事物之前。特别是,您可能能够重新排序管道和类似的链式函数,以便类型化对象排在第一位。
  • Annotate as needed. One common trick is to add annotations until everything works, and then take them away one by one until you have the minimum needed. Do try to avoid annotating if possible. Not only is it not aesthetically pleasing, but it makes the code more brittle. It is a lot easier to change types if there are no explicit dependencies on them.
于 2012-12-11T14:44:07.800 回答