几点:
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.