# Haskell/Truth values

## Equality and other comparisons

[edit | edit source]In the last chapter, we used the equals sign to define variables and functions in Haskell as in the following code:

```
r = 5
```

That means that the evaluation of the program replaces all occurrences of `r`

with `5`

(within the scope of the definition). Similarly, evaluating the code

```
f x = x + 3
```

replaces all occurrences of `f`

followed by a number (`f`

's argument) with that number plus three.

Mathematics also uses the equals sign in an important and subtly different way. For instance, consider this simple problem:

**Example:** Solve the following equation:

Our interest here isn't about representing the value as , or vice-versa. Instead, we read the equation as a *proposition* that some number gives 5 as result when added to 3. Solving the equation means finding which, if any, values of make that proposition true. In this example, elementary algebra tells us that (i.e. 2 is the number that will make the equation true, giving ).

Comparing values to see if they are equal is also useful in programming. In Haskell, such tests look just like an equation. Since the equals sign is already used for defining things, Haskell uses a *double* equals sign, `==`

instead. Enter our proposition above in GHCi:

Prelude> 2 + 3 == 5 True

GHCi returns "True" because is equal to 5. What if we use an equation that is not true?

Prelude> 7 + 3 == 5 False

Nice and coherent. Next, we will use our own functions in these tests. Let's try the function `f`

we mentioned at the start of the chapter:

Prelude> let f x = x + 3 Prelude> f 2 == 5 True

This works as expected because `f 2`

evaluates to `2 + 3`

.

We can also compare two numerical values to see which one is larger. Haskell provides a number of tests including: `<`

(less than), `>`

(greater than), `<=`

(less than or equal to) and `>=`

(greater than or equal to). These tests work comparably to `==`

(equal to). For example, we could use `<`

alongside the `area`

function from the previous module to see whether a circle of a certain radius would have an area smaller than some value.

Prelude> let area r = pi * r ^ 2 Prelude> area 5 < 50 False

## Boolean values

[edit | edit source]What is actually going on when GHCi determines whether these arithmetical propositions are true or false? Consider a different but related issue. If we enter an arithmetical expression in GHCi the expression gets *evaluated*, and the resulting numerical value is displayed on the screen:

Prelude> 2 + 2 4

If we replace the arithmetical expression with an equality comparison, something similar seems to happen:

Prelude> 2 == 2 True

Whereas the "4" returned earlier is a number which represents some kind of count, quantity, etc., "True" is a *value* that stands for the truth of a proposition. Such values are called **truth values**, or **boolean values**.^{[1]} Naturally, only two possible boolean values exist: `True`

and `False`

.

### Introduction to types

[edit | edit source]`True`

and `False`

are real values, not just an analogy. Boolean values have the same status as numerical values in Haskell, and you can manipulate them in similar ways. One trivial example:

Prelude> True == True True Prelude> True == False False

`True`

is indeed equal to `True`

, and `True`

is not equal to `False`

. Now: can you answer whether `2`

is equal to `True`

?

Prelude> 2 == True <interactive>:1:0: No instance for (Num Bool) arising from the literal ‘2’ at <interactive>:1:0 Possible fix: add an instance declaration for (Num Bool) In the first argument of ‘(==)’, namely ‘2’ In the expression: 2 == True In an equation for ‘it’: it = 2 == True

Error! The question just does not make sense. We cannot compare a number with a non-number or a boolean with a non-boolean. Haskell incorporates that notion, and the ugly error message complains about this. Ignoring much of the clutter, the message says that there was a number (`Num`

) on the left side of the `==`

, and so some kind of number was expected on the right side; however, a boolean value (`Bool`

) is not a number, and so the equality test failed.

So, values have **types**, and these types define limits to what we can or cannot do with the values. `True`

and `False`

are values of type `Bool`

. The `2`

is complicated because there are many different types of numbers, so we will defer that explanation until later. Overall, types provide great power because they regulate the behavior of values with rules that *make sense*, making it easier to write programs that work correctly. We will come back to the topic of types many times as they are very important to Haskell.

## Infix operators

[edit | edit source]An equality test like `2 == 2`

is an expression just like `2 + 2`

; it evaluates to a value in pretty much the same way. The ugly error message we got on the previous example even says so:

In the expression: 2 == True

When we type `2 == 2`

in the prompt and GHCi "answers" `True`

, it is simply evaluating an expression. In fact, `==`

is itself a function which takes two arguments (which are the left side and the right side of the equality test), but the syntax is notable: Haskell allows two-argument functions to be written as *infix operators* placed *between* their arguments. When the function name uses only non-alphanumeric characters, this infix approach is the common use case. If you wish to use such a function in the "standard" way (writing the function name before the arguments, as a *prefix operator*) the function name must be enclosed in parentheses. So the following expressions are completely equivalent:

Prelude> 4 + 9 == 13 True Prelude> (==) (4 + 9) 13 True

Thus, we see how `(==)`

works as a function similarly to `areaRect`

from the previous module. The same considerations apply to the other *relational operators* we mentioned (`<`

, `>`

, `<=`

, `>=`

) and to the arithmetical operators (`+`

, `*`

, etc.) – all are functions that take two arguments and are normally written as infix operators.

In general, we can say that tangible things in Haskell are either values or functions.

## Boolean operations

[edit | edit source]Haskell provides three basic functions for further manipulation of truth values as in logic propositions:

`(&&)`

performs the*and*operation. Given two boolean values, it evaluates to`True`

if both the first and the second are`True`

, and to`False`

otherwise.

Prelude> (3 < 8) && (False == False) True Prelude> (&&) (6 <= 5) (1 == 1) False

`(||)`

performs the*or*operation. Given two boolean values, it evaluates to`True`

if at least one of them is`True`

and to`False`

otherwise.

Prelude> (2 + 2 == 5) || (2 > 0) True Prelude> (||) (18 == 17) (9 >= 11) False

`not`

performs the negation of a boolean value; that is, it converts`True`

to`False`

and vice-versa.

Prelude> not (5 * 2 == 10) False

Haskell libraries already include the relational operator function `(/=)`

for *not equal to*, but we could easily implement it ourselves as:

```
x /= y = not (x == y)
```

Note that we can write operators infix even when defining them. Completely new operators can also be created out of ASCII symbols (which means mostly the common symbols used on a keyboard).

## Guards

[edit | edit source]Haskell programs often use boolean operators in convenient and abbreviated syntax. When the same logic is written in alternative styles, we call this *syntactic sugar* because it sweetens the code from the human perspective. We'll start with *guards*, a feature that relies on boolean values and allows us to write simple but powerful functions.

Let's implement the absolute value function. The absolute value of a real number is the number with its sign discarded; so if the number is negative (that is, smaller than zero) the sign is inverted; otherwise it remains unchanged. We could write the definition as:

Here, the actual expression to be used for calculating depends on a set of propositions made about . If is true, then we use the first expression, but if is the case, then we use the second expression instead. To express this decision process in Haskell using guards, the implementation could look like this:^{[2]}

**Example:** The absolute value function.

```
absolute x
| x < 0 = -x
| otherwise = x
```

Remarkably, the above code is about as readable as the corresponding mathematical definition. Let us dissect the components of the definition:

- We start just like a normal function definition, providing a name for the function,
`absolute`

, and saying it will take a single argument, which we will name`x`

.

- Instead of just following with the
`=`

and the right-hand side of the definition, we enter the two alternatives placed below on separate lines.^{[3]}These alternatives are the*guards*proper. Note that the whitespace (the indentation of the second and third lines) is not just for aesthetic reasons; it is necessary for the code to be parsed correctly.

- Each of the guards begins with a pipe character,
`|`

. After the pipe, we put an expression which evaluates to a boolean (also called a boolean condition or a*predicate*), which is followed by the rest of the definition. The function only uses the equals sign and the right-hand side from a line if the predicate evaluates to`True`

.

- The
`otherwise`

case is used when none of the preceding predicates evaluate to`True`

. In this case, if`x`

is not smaller than zero, it must be greater than or equal to zero, so the final predicate could have just as easily been`x >= 0`

; but`otherwise`

works just as well.

*Note*

There is no syntactical magic behind `otherwise`

. It is defined alongside the default variables and functions of Haskell as simply

```
otherwise = True
```

This definition makes *otherwise* a catch-all guard. As evaluation of the guard predicates is sequential, the `otherwise`

predicate will only be reached if none of the previous cases evaluate to `True`

(so make sure you always place *otherwise* as the last guard!). In general, it is a good idea to always provide an `otherwise`

guard, because a rather ugly runtime error will be produced if none of the predicates is true for some input.

*Note*

In the first guard

```
| x < 0 = -x
```

we used the minus sign to negate `x`

. It is worth noting that this way of expressing sign inversion is a special case of sorts, in that the `-`

is *not* a function that takes one argument and evaluates to `0 - x`

, but merely a syntactical abbreviation. While very handy, this abbreviation occasionally conflicts with the usage of `(-)`

as an actual function (the subtraction operator), which is a potential source of annoyance (for example, try writing three minus negative-four without using any parentheses for grouping).

That being so, when testing `absolute`

with negative numbers you should call it like this:

Prelude> absolute (-10) 10

`where`

and Guards

[edit | edit source]`where`

clauses work well along with guards. For instance, consider a function which computes the number of (real) solutions for a quadratic equation, :

```
numOfRealSolutions a b c
| disc > 0 = 2
| disc == 0 = 1
| otherwise = 0
where
disc = b^2 - 4*a*c
```

The `where`

definition is within the scope of all of the guards, sparing us from repeating the expression for `disc`

.

## Notes

- ↑ The term is a tribute to the mathematician and philosopher George Boole.
- ↑ This function is already provided by Haskell with the name
`abs`

, so in a real-world situation you don't need to provide an implementation yourself. - ↑ We
*could*have joined the lines and written everything in a single line, but it would be less readable.