# More polymorphism and type classes

CIS 194 Week 5

11 February 2013

Haskell’s particular brand of polymorphism is known as *parametric* polymorphism. Essentially, this means that polymorphic functions must work *uniformly* for any input type. This turns out to have some interesting implications for both programmers and users of polymorphic functions.

## Parametricity

Consider the type

`a -> a -> a`

Remember that `a`

is a *type variable* which can stand for any type. What sorts of functions have this type?

What about this:

```
f :: a -> a -> a
f x y = x && y
```

It turns out that this doesn’t work. The syntax is valid, at least, but it does not type check. In particular we get this error message:

```
2012-02-09.lhs:37:16:
Couldn't match type `a' with `Bool'
`a' is a rigid type variable bound by
the type signature for f :: a -> a -> a at 2012-02-09.lhs:37:3
In the second argument of `(&&)', namely `y'
In the expression: x && y
In an equation for `f': f x y = x && y
```

The reason this doesn’t work is that the *caller* of a polymorphic function gets to choose the type. Here we, the *implementors*, have tried to choose a specific type (namely, `Bool`

), but we may be given `String`

, or `Int`

, or even some type defined by someone using `f`

, which we can’t possibly know about in advance. In other words, you can read the type

`a -> a -> a`

as a *promise* that a function with this type will work no matter what type the caller chooses.

Another implementation we could imagine is something like

```
f a1 a2 = case (typeOf a1) of
Int -> a1 + a2
Bool -> a1 && a2
_ -> a1
```

where `f`

behaves in some specific ways for certain types. After all, we can certainly implement this in Java:

```
class AdHoc {
public static Object f(Object a1, Object a2) {
if (a1 instanceof Integer && a2 instanceof Integer) {
return (Integer)a1 + (Integer)a2;
} else if (a1 instanceof Boolean && a2 instanceof Boolean) {
return (Boolean)a1 && (Boolean)a2;
} else {
return a1;
}
}
public static void main (String[] args) {
System.out.println(f(1,3));
System.out.println(f(true, false));
System.out.println(f("hello", "there"));
}
}
[byorgey@LVN513-9:~/tmp]
```