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:
>>> 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:
>>> True && False
False
>>> True || False
True
Negation is a bit different from other languages. Instead of !(2 < 3)
, we write
>>> 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:
>>> 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.