# Type inference in Golang/Haskell

I've read that Go doesn't actually have true type inference in the sense that functional languages such as ML or Haskell have, but I haven't been able to find a simple to understand comparison of the two versions. Could someone explain in basic terms how type inference in Go differs from type inference in Haskell, and the pros/cons of each?

## 2 Answers

See this StackOverflow answer regarding Go's type inference. I'm not familiar with Go myself but based on this answer it seems like a one-way "type deduction" (to borrow some C++ teminology). It means that if you have:

``````x := y + z
``````

then the type of `x` is deduced by figuring out the type of `y + z`, which is a relatively trivial thing to do for the compiler. To do this, the types of `y` and `z` need to be known a priori: this could be done via type annotations or inferred from the literals assigned to them.

In contrast, most functional languages have type inference that uses all possible information within a module (or function, if the inference algorithm is local) to derive the type of the variables. Complicated inference algorithms (such as Hindley-Milner) often involve some form of type unification (a bit like solving equations) behind the scenes. For example, in Haskell, if you write:

``````let x = y + z
``````

then Haskell can infer the type not just `x` but also `y` and `z` simply based on the fact that you're performing addition on them. In this case:

``````x :: Num a => a
y :: Num a => a
z :: Num a => a
``````

(The lowercase `a` here denotes a polymorphic type, often called "generics" in other languages like C++. The `Num a =>` part is a constraint to indicate that the type `a` support have some notion of addition.)

Here's a more interesting example: the fixed-point combinator that allows any recursive function to be defined:

``````let fix f = f (fix f)
``````

Notice that nowhere have we specified the type of `f`, nor did we specify the type of `fix`, yet the Haskell compiler can automatically figure out that:

``````f :: t -> t
fix :: (t -> t) -> t
``````

This says that:

• The parameter `f` must be a function from some arbitrary type `t` to the same type `t`.
• `fix` is a function that receives a parameter of type `t -> t` and returns a result of type `t`.
• more exactly, Haskell can tell that `x`, `y`, `z` are the same `Num`eric type, but they can still be `Integer`s, `Double`s, `Ratio Integer`s... Haskell is willing to make an arbitrary choice between numeric types, but not for other typeclasses. – John Dvorak Aug 17 '14 at 9:52

Type inference in Go is extremely limited and extremely simple. It works only in one language construct (variable declaration) and it simply takes the type of the right-hand side and uses it as the type for the variable on the left-hand side.

Type inference in Haskell can be used everywhere, it can be used to infer the types for the whole program. It is based on unification, which means that (conceptually) all types are inferred "at once" and they can all influence each other: in Go, type information can only flow from the right-hand side of a variable declaration to the left-hand side, never in the other direction and never outside of a variable declaration; in Haskell, type information flows freely in all directions through the entire program.

However, Haskell's type system is so powerful that type inference can actually fail to infer a type (or more precisely: restrictions have to be put in place so that a type can always be inferred). Go's type system is so simple (no subtyping, no parametric polymorphism) and its inference so limited that it always succeeds.

• "in Haskell, type information flows freely in all directions through the entire program": I find this gives a very good intuition. +1 – Giorgio Aug 17 '14 at 9:45
• The claims that this answer makes in the last paragraph are a bit misleading. Haskell has no subtyping. Furthermore, parametric polymorphism doesn't cause any problem for the completeness of type inference: Hindley-Milner on the polymorphic lambda calculus always finds the most general type. Haskell can fail to infer types, but this will be on sophisticated type system features like GADTs where, when naively formulated, no principal (i.e., "best choice") type exists. – Edward Z. Yang Mar 18 '16 at 22:21