In Expert F# 2.0 by Don Syme, Adam Granicz, and Antonio Cisternino, pg. 44
Type inference: Using the |> operator lets type information flow from input objects to the functions manipulating those objects. F# uses information collected from type inference to resolve some language constructs such as property accesses and method overloading. This relies on information being propagated left to right thorough the text of a program. In particular, type information to the right of a position isn't taken into account when resolving property access and overload.
So clearly using |> can help type inference.
As always, declaring the type is also helpful.
Are there any other means/tactics that can be used to help F# type inference?
EDIT
As RamonSnir correctly pointed out one is supposed to let type inference do as much work as possible. So adding type declarations just because you can is not what one should do. Do not take this question or answers as something that should be done. I asked the question to help better understand the nuance of type inference and what might help in those occasions when type inference needs help. So if type inference can resolve all of the types without help, then don't give it any, but when it does, it would be nice to know some ways to help it.
A few points:
1) Prefer module functions to properties and methods.
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) Prefer methods without overloading. For example, QuickLinq Helpers define non-overloaded members to avoid a bunch of type annotation in LINQ extension methods.
3) Make use of any available information to give some hints to the type checker.
let makeStreamReader x = new System.IO.StreamReader(x) // fails
let makeStreamReader x = new System.IO.StreamReader(path=x) // works
The last example is taken from an excellent write-up about F# type inference.
To conclude, you don't often need to help F# type checker. If there is a type error, the summary from the link above gives a good fixing guideline:
So to summarize, the things that you can do if the compiler is complaining about missing types, or not enough information, are:
- Define things before they are used (this includes making sure the files are compiled in the right order)
- Put the things that have "known types" earlier than things that have "unknown types". In particular, you might be able reorder pipes and similar chained functions so that the typed objects come first.
- 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With