Here's a slightly longer example of Haskell's awesome type inference with some additional commentary to complement the example that elbenshira gave: >>> let showAdd x y = show (x + y)
>>> :type showAdd
showAdd :: (Num a, Show a) => a -> a -> String
The compiler infers:* The two arguments, `x` and `y`, must be some type `a` * They must be the same type `a` * The type `a` must implement the `Num` interface (because we add them together using `(+)` * The result of addition must also be the same type `a` * The type `a` must also implement the `Show` interface (because we call `show` on the result of addition, which also has type `a`) Notice how the compiler works backwards from the call to `show` on the result of addition to infer that the two original arguments must also implement the `Show` interface. We didn't need to annotate any argument types or interfaces: the compiler did all the work for us. This is what people mean when they say that Haskell has "global" type inference. A language like Rust has "local" type inference, meaning that you have to help a the compiler a little bit by providing the types and interfaces of function arguments, but then the compiler can infer the types of locally bound variables from that point forward. |