Skip to content

Booleans

There is not all that much to be said about Booleans. They are represented by the type Bool in Haskell, which has exactly two values, True and False. We can produce them using various types of logical tests:

GHCi
>>> 1 < 2
True
>>> :t 1 < 2
1 < 2 :: Bool

As in most modern programming languages, and unlike in C, Bool and Int are distinct types.

We have the standard logical operators:

GHCi
>>> True && False
False
>>> True || False
True

Negation is a bit different from other languages. Instead of !(2 < 3), we write

GHCi
>>> not (2 < 3)
False

There are two reasons for this. First, given that ! is a special character, we'd have to write (!) (2 < 3) if we wanted to use ! in prefix notation. Remember the distinction between "normal" functions to be written in prefix notation and operators (composed of special characters) to be written in infix notation. Second, the (!) operator is in fact used as the operator for indexing into arrays.

Also as in most programming languages you are used to, (&&) and (||) are short-circuiting operators. This means that in the expression x && y or x || y, y is evaluated only if this is necessary to determine the result of the whole expression. For example, if x is True, then x || y is True no matter the value of y, so y would not be evaluated. Similarly, y is not evaluated in the expression x && y if x is False.

Different from other programming languages, this short-circuiting behaviour of (&&) and (||) is not bolted into the language via special treatment of these operations by the compiler. We get this behaviour for free due to Haskell's lazy evaluation.

Similarly, the Boolean type is not actually a built-in type in Haskell. It is defined as part of the standard library as

data Bool = False | True

We will discuss type definitions like this one later in this book. Intuitively, this definition is not hard to read. We have a data type Bool that can have one of two values, False or True.

The Bool type also supports equality tests and ordering:

GHCi
>>> False == True
False
>>> False < True
True

This can be useful when you want to sort a list by some Boolean attribute. It is also useful to express Boolean operators other than (&&) and (||). x <= y is the same as "x implies y", x == y is the same as "x if and only if y", and x /= y is the same as x `xor` y, only there is no xor function in Haskell, exactly because we can use (/=) to the same effect.