Enumerated type

Enumerated type #

An enumerated type is a finite set of alternative values.

Example. A playing card can have one of four suits: Clubs, Diamonds, Hearts or Spades.

In the first assignment, we modeled these values as four characters 'C', 'D', 'H' or 'S'. This solution is unsatisfying, because the type Char allows other letters. Instead, we could declare an enumerated type (for instance named Suit) with 4 possible values (Clubs, Diamonds, Hearts and Spades).

In Haskell #

Syntax. An enumerated type in Haskell can be written

data <enumerated type name> = <value 1> | ... | <value n>

where:

  • the type name and the values start with a capital letter, and
  • values are distinct.

Example.

data Suit = Clubs | Diamonds | Hearts | Spades

Note. The type Bool in Haskell is an enumerated type (with values True and False):

data Bool = False | True

An enumerated type can be used like a regular one (e.g. in a pattern).

Example.

data Suit = Clubs | Diamonds | Hearts | Spades

-- pattern matching
isRed :: Suit -> Bool
isRed Diamonds = True
isRed Hearts = True
isRed _ = False

Warning. By default, when we create a type, it does not support functions like ==, /=, show, print, etc.

A solution is the keyword deriving. It lets us declare that our type belongs to some type classes. The compiler will automatically implement the function associated these classes for our type.
For instance:

data Suit = Clubs | Diamonds | Hearts | Spades
  deriving (Eq, Show) -- declare that `Suit` belongs to the type classes `Eq` and `Show`

isSmooth :: Suit -> Bool
-- we can use /= here to compare two suits
isSmooth s = s /= Spades

next :: Suit -> Suit
next Clubs = Diamonds
next Diamonds = Hearts
next Hearts = Spades
next Spades = Clubs

main :: IO ()
-- we can use `print` here to display the value of a suit
main = print $ next Hearts

This observation holds for the other composite types seen in this section (product type and sum type).