Bound

Bound #

In some scenarios, a regular type variable may be too generic.

Example. We may want to write an algorithm where the input can have any numeric type (integer, float, etc.).

A type variable in this case is too generic, because it can also stand for a non-numeric type (e.g. string, Boolean value, a function type, etc.).

In Haskell #

Example. The following function does not compile, because the operation + is not defined for arbitrary types.

timesTwo :: a -> a   -- arbitrary type `a`
timesTwo x = x + x   -- compilation error: `a`s may not be "summable"

In order to restrict a to numeric types, we can use a so-called “type class constraint” (defined below).

Type class #

A type class in Haskell stands for a set of possible types.

Example. Num is the class of numeric types.

The types Int, Integer or Float belong to this class.

A type class is associated with one or several functions.

Each type that belongs to this class must support these functions.

Example (continued). The types that belong to the class Num must support the functions +, *, etc.

Examples. We will use the following type classes:

type class supported functions
Eq ==, /=
Ord ==, /=, <, <=, >, >=, …
Num +, *, ^, …
Integral +, *, ^, div (integer division), mod (modulo), …
Show show (returns a human readable string), print, …
Functor fmap
Monad fmap, return, join, >>=, >=>, …

Disclaimer. We will not see in this course how to create a type class.

For details, we refer (for instance) to this page.

Usage #

We can use a type class to restrict a type variable to certain types.

Syntax. A type class constraint has the form

<type class> <type variable>

Examples.

  • The type class constraint Num a restricts the variable a to numeric types.
  • The type class constraint Eq a restricts the variable a to types that support equality (==) and inequality (\=).

Syntax. A type can be preceded with one or several type constraints, followed by a =>:

(<constraint 1>, ..., <constraint n>) => <type>

Example (continued). We can rewrite the function timesTwo above as

-- This function compiles (as opposed to the one above)
timesTwo :: (Num a) => a -> a
timesTwo x = x + x

The type class constraint Num a requires a to be a numeric type. This function compiles, because numeric types must implement the function +.

Example.

-- Returns true iff the input list consists of two identical elements
myFunction :: (Eq a) => [a] -> Bool
myFunction [x,y] = x == y
myFunction _ = False

Hint. The Haskell compiler (or your IDE) may suggest you type class constraints if your code does not compile.

To go further. A type class can be a subclass of another.
For instance:

  • Integral is a subclass of Num,
  • Ord is a subclass of Eq.

We will not cover this notion in this course.