Let’s talk about type signatures.

`hello :: String -> Int -> String`

Pretty clear what is going on, right? Seems fine. What about this lad?

`wtflol :: (Show a, Num b) => a -> [a] -> b -> (a, b)`

That’s pretty unhelpful to be honest.

What are these letters doing in our types when we wanted, well, types?

Let’s work up from a simple one to a stupid one and maybe learn something along the way. Good? Great.

### Probably the worst function ever

Here is a type signature for a mysterious function:

`spooky :: a -> a`

Given any `a`

, and knowing nothing about that `a`

, what is the only thing that we can do with it?

If you guessed “just return it”, then yes, you were right. It’s the classic `identity`

function.

```
identity :: a -> a
= a
identity a -- identity 10 == 10
```

What do you think this function does?

`mystery :: a -> b -> a`

Since we don’t know anything about `b`

, and the function returns an `a`

, then all we can do is ignore the `b`

altogether. This is called the `const`

function, and is used when we have to want to make a `map`

function do not very much at all.

```
const :: a -> b -> a
const a _ = a
-- const "dog" 100 == "dog"
```

Hopefully the pattern you are seeing here is that if we know nothing about our variables, then there is actually very little we can do with them.

### Lists of mysterious things

A place most people come across polymorphism quite early on in their Haskell careers is in stuff like lists. Instead of one function that works on `List String`

, and another one `List Int`

, and another on `List (Maybe Tuple (Int, String))`

we can use polymorphism to act upon the structure of the list itself but not the items inside.

With this in mind, and given that `[a]`

means a `List`

that is full of zero or more `a`

values, what possible things could this function do to our `[a]`

?

`thing :: [a] -> [a]`

According to the function search engine Hoogle - not a huge amount. It lists four functions that match this signature - and two of them throw exceptions if passed an empty list so they’re not the kind of functions that we like to spend our time with. This leaves:

`cycle`

- this repeats the list of values infinitely.`reverse`

- reverses the order of the list.

The important thing is that since we don’t know anything about what the hell `a`

is, all the functions can do is mess around with the ordering a bit, as is their right, I suppose. How can we find out more about these `a`

and `b`

values without concretely specifying what they are?

### Constraints

If there’s anything going on before the `=>`

in a type signature, there’s a good chance it’s a `constraint`

. These are rules that apply to each type they refer to. Here, we are using a constraint on `a`

, that says “I don’t care what `a`

is, so long as it has a `Show`

instance”.

```
showTheList :: Show a => [a] -> String
= ""
showTheList [] : as) = show a ++ ", " ++ showTheList as
showTheList (a -- showTheList [1,2,3] == "1, 2, 3, "
```

Therefore, the only thing we can really do to these `a`

values is `show`

them, as we don’t know anything else about it.

We can do something similar with the `Num`

typeclass (which is the typeclass of numbers).

```
addStuffUp :: Num a => [a] -> a
= 0
addStuffUp [] : as) = a + addStuffUp as
addStuffUp (a -- addStuffUp [1,2,3] == 6
```

Here, the constraint means we don’t mind which kind of number we are passed - since they all implement `+`

so we can add them together.

We can have as many constraints as we like on our variables (often multiple ones on the same value, such as `(Show a, Ord a) =>`

for things that can be sorted and eventually turned into strings) - and can use any typeclass to do the restraining.

I hope this makes sense. This started melting into something about IO testing, but I have decided to spin that into a separate post before this one spirals out of control, so let’s stop for now. Thanks.

Make sense? If not, why not get in touch?

Further reading: