For me, this article was the one where it &quot;clicked&quot;: <a href="http:&#x2F;&#x2F;okmij.org&#x2F;ftp&#x2F;Haskell&#x2F;AlgorithmsH.html#teval" rel="nofollow">http:&#x2F;&#x2F;okmij.org&#x2F;ftp&#x2F;Haskell&#x2F;AlgorithmsH.html#teval</a>. Summary: type inference is just &quot;evaluating&quot; the program&#x2F;expression, but the result is a type instead of a value. Each time you evaluate a function call, use unification to bind the arguments rather than pattern matching. Another way to understand it: pattern matching only works &quot;one way&quot;, whereas unification works &quot;both ways&quot; - implying the caller&#x27;s types as well as the callee&#x27;s types. It also has a nice introduction of using a monad to simplify state management.