## Adventures in Haskell – Type inference

I’m learning Haskell, so I thought I’d write about my adventures as I go along.

One of the first things I noticed about Haskell (apart from the obvious, such as being functional) is that it is very good about type inference. This means that the vast majority of the time, I don’t need to tell Haskell what types to use for my functions (although it’s good style), and I don’t have to tell it what types to use for my variables. For example, consider this simple, inefficient function for calculating the Fibonacci sequence:

```fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)```

Haskell was able to automatically infer that the function has the type `(Num t, Num t1) => t -> t1`, which means it takes a number and returns a number. Even though I didn’t declare any types, it’s still strongly typed; if I try to execute `fib "1"`, I get the error “`No instance for (Num [Char])`“, which is Haskell’s way of saying that a string (a list of characters) is not a number.

As I said, it’s good practice to declare the types of functions. In this case, our code should look like this:

```fib :: (Integral t) => t -> t
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)```

This tells it the input should be an `Integral` type (either `Int` or `Integer`, equivalent to Java’s `int` or `BigInteger`). I’ve restricted it because, while passing it 10.0 is fine, passing it 10.1 will not terminate. Passing it -1 will also not terminate, but that’s a separate issue. It also says that the output type is the same as the input type, unlike the inferred types, where the input may be an `Int` while the output’s an `Integer`. Notice how there’s only one type variable `t` instead of `t` and `t1`.

There are cases where type inference fails. One example is passing the output of a function that can return anything into a function that can accept anything. Specifically, `print (read "1")` will fail to compile with the error “`Ambiguous type variable `a' in the constraints`“. The type for `read` is `(Read a) => String -> a`, and the type for `print` is `(Show a) => a -> IO ()`. The type variable `a` can be matched with any type that has an instance for `Show` and `Read` (implements the interfaces, in Java terminology). Since many will fit, the compiler does not not which one to use. In this case, we have to tell it like so: `print (read "1" :: Int)`.