Haskell permits user defined datatypes. We can define structured
types such as trees, stacks, queues .... To do this, we define new
names, called *constructors*, to denote the components of the new
type. In general, a constructor takes arguments. The simplest type
of constructor is a constant, one that takes 0 arguments.

The simplest user defined datatype is an enumerated type, such as

data day = Sun | Mon | Tue | Wed | Thu | Fri | Sat

More interesting are recursive types, such as a binary tree where each node can hold an integer.

data Btreeint = Nil | Node Int Btreeint Btreeint

This says that a binary tree of integers, `Btreeint`, is either
an empty tree, `Nil`, or a node which holds an integer value and
contains two nested trees, corresponding to the left and right
children.

Can we define polymorphic datatypes, like polymorphic functions? For instance, can we define just the structure of a binary tree without fixing the type of value stored at each node?

Yes, we can, using the notion of a type variable, as before.

data Btree a = Nil | Node a (Btree a) (Btree a)

Note here that the complete name of the new type is `Btree a` not
just `Btree`.

To take another example, we can redefine the builtin type list as follows:

data List a = Nil | Cons a (List a)

The next step is to declare that a user defined datatype belongs to a
type class such as `Eq` or `Ord`. Each type class is
characterized by a set of functions that each member of the class must
support--analogous to an interface in Java. For instance, for a type
to belong to `Eq`, it must support an equality check, denoted
`==`. The exact implementation of `==` is irrelevant. For
instance, we might define `==` on trees to be isomorphism and
place `Btreeint` in `Eq` as follows.

instance Eq Btreeint where Nil == Nil = True (Node x t1 t2) == (Node y u1 u2) = (x == y) && (t1 == u1) && (t2 == u2)

The definition of `==` for `Btreeint` follows the normal
syntax of a Haskell function definition--in this example, by cases.

How about making `Btree a` an element of `Eq`? We could
analogously write

instance Eq (Btree a) where Nil == Nil = True (Node x t1 t2) == (Node y u1 u2) = (x == y) && (t1 == u1) && (t2 == u2)

Notice however, that this uses the test `x == y` for elements of
the unspecified type `a`. In `Btreeint` this was not a
problem because the type of `x` and `y` was known to be
`Int`, which belongs to `Eq`. Here, instead, we must make
the membership of `Btree a` in `Eq` conditional on the
properties of the underlying type `a`, as follows.

instance Eq a => Eq (Btree a) where Nil == Nil = True (Node x t1 t2) == (Node y u1 u2) = (x == y) && (t1 == u1) && (t2 == u2)

In other words, ``if `a` is in `Eq`, then `Btree a` is
in `Eq` with `==` defined as ...''

We have to be a bit careful here. With the definitions we have given, the Haskell interpreter responds as follows,

Main> (Node 5 Nil Nil) == (Node 6 Nil Nil) False Main> (Node 5 Nil Nil) == (Node 5 Nil Nil) True

which is as we expect, but, somewhat unexpectedly, it says

Main> Nil == Nil ERROR - Unresolved overloading *** Type : Eq a => Bool *** Expression : Nil == Nil

This is because if we just say `Nil`, the interpreter cannot
instantiate `a` to a concrete type and determine whether it
belongs to `Eq` or not. The same happens if we try to ask
whether `[] == []` for the empty list that is built in to
Haskell. To get around this, we have to explicitly supply information
about the base type of the tree or list as follows.

Main> (Nil::Btree Int) == Nil True Main> ([]::[Float]) == [] False

Notice that it is sufficient to specify the base type for `[]` on
one side of the equation. Interestingly, even if we try, we cannot
assert that there are two different instances of `[]` in an
expression. For instance, if we try the following

Prelude> ([]::[Float]) == ([]::[Int])

the response is

ERROR - Type error in application *** Expression : [] == [] *** Term : [] *** Type : [Float] *** Does not match : [Int]