In this chapter we introduce mechanisms for declaring new types and classes in Haskell. We start with three approaches to declaring types, then consider recursive types, show how to declare classes and their instances, and conclude by developing a tautology checker and an abstract machine.
Type declarations
The simplest way of declaring a new type is to introduce a new name for an existing type, using the type mechanism of Haskell. For example, the following declaration from the standard prelude states that the type String is just a synonym for the type [Char] of lists of characters:
As in this example, the name of a new type must begin with a capital letter. Type declarations can be nested, in the sense that one such type can be declared in terms of another. For example, if we were defining a number of functions that transform coordinate positions, we might declare a position as a pair of integers, and a transformation as a function on positions:
type Pos = (Int,Int)
type Trans = Pos -> Pos
However, type declarations cannot be recursive. For example, consider the following recursive declaration for a type of trees:
That is, a tree is a pair comprising an integer and a list of subtrees. While this declaration is perfectly reasonable, with the empty list of subtrees forming the base case for the recursion, it is not permitted in Haskell because it is recursive. If required, recursive types can be declared using the more powerful data mechanism, which will be introduced in the next section.
Type declarations can also be parameterised by other types. For example, if we were defining a number of functions that manipulate pairs of values of the same type, we could declare a synonym for such pairs:
Finally, type declarations with more than one parameter are possible too. For example, a type of lookup tables that associate keys of one type to values of another type can be declared as a list of (key,value) pairs:
Using this type, a function that returns the first value that is associated with a given key in a table can then be defined as follows:
Data declarations
A completely new type, as opposed to a synonym for an existing type, can be declared by specifying its values using the data mechanism of Haskell.