# 1.3 Types make everything easier

In programming, types are a way of classifying data under specific
labels. In math, you have the set of *real numbers*, which are
numbers with a decimal point. You cannot count real numbers, because
there are infinitely many of them between the values of `1.0`

and
`2.0`

. You also have *integers*, which are countable (whole)
numbers (e.g. 1, 2, 3). Just by knowing what type of number you are
working with, you already know a lot about how it behaves without
having to test each value individually to see if it has certain
properties. The same is true of types in programming. Types give you
insight into the properties of your data, which makes them a valuable
tool when writing programs.

So far we have only been working with numbers—specifically
floating-point numbers (numbers that have a decimal point). These are
like the numbers that you know from math, except they do not have
infinite precision. Floating-point numbers are a form of scientific
notation, which means that they are approximations to some number of
significant digits. There are two different versions: single-precision
and double-precision. In Haskell, these are called, respectively,
`Float`

and `Double`

. By default, Haskell uses `Double`

when you do not specify which one you want to use. You can see the
difference in the example below.

```
> pi :: Double
3.141592653589793
> pi :: Float
3.1415927
```

In this example, I added a *type annotation* to the expression
telling ghci how to interpret the number. I can do this because
`pi`

is defined in such a way that it can be used as a
`Double`

or a `Float`

depending on the context. This is a
more advanced feature of Haskell that we will come back to in a later
chapter.

Besides floating-point numbers, there are also integers (whole numbers
without a decimal point). In Haskell, these are called `Integer`

,
and can be infinitely large (or infinitely small for negative values).

```
> 9223372036854775807 * 9223372036854775807
85070591730234615847396907784232501249
```

There are other types of data we can use in our expressions beyond
numbers. Using Haskell’s boolean operators, you can construct
expressions that are either `True`

or `False`

, which are the
only two possible values of the Haskell type `Bool`

. Below is a
table of useful boolean operators.

operator | meaning |
---|---|

`>` | greater than |

`<` | less than |

`>=` | greater than or equal to |

`<=` | less than or equal to |

`==` | equal to |

`/=` | not equal to |

Let’s try them out in ghci.

```
> 3 >= 5
False
> 1 < 2
True
> 3 == 3
True
> 4 /= 5
True
```

Boolean operators have a lower precedence than arithmetic operators, so you can be sure that when you write an expression that mixes the two, the arithmetic parts of the expression will be grouped together without needing explicit parentheses.

```
> 2 * 3 /= 2 + 2
True
```

The example above is equivalent to the following.

```
> (2 * 3) /= (2 + 2)
True
```

You can combine two boolean expressions together using the logical operators, shown below.

operator | meaning |
---|---|

`&&` | logical and |

`||` | logical or |

For `&&`

to evaluate to `True`

, *both* subexpressions
must evaluate to `True`

, otherwise the whole expression is
`False`

. In contrast, `||`

requires only *one*
subexpression to be `True`

for the entire expression to be
`True`

, and is only `False`

if *both* subexpressions are
`False`

.

```
> True && False
False
> True && True
True
> False || True
True
> False || False
False
```

Try the following exercises.

Write a lambda expression that computes if a given number is greater than 0, but less than 5.

```
\ a -> a > 0 && a < 5
```

We can test it to make sure it is correct.

```
> test = \ a -> a > 0 && a < 5
> test 4
True
> test (-2)
False
> test 17
False
```

Note that we need to wrap the `-2`

in parentheses so that the
minus sign is not interpreted as subtraction.

Write a lambda expression that computes if a given number is negative or is equal to 27.

```
\ a -> a < 0 || a == 27
```

We can test it to make sure it is correct.

```
> test = \ a -> a < 0 || a == 27
> test (-9)
True
> test 301
False
> test 27
True
```

We now have four different types that we can use in our expressions:
`Float`

, `Double`

, `Integer`

, and `Bool`

. So far,
ghci has been inferring the types that we want to use instead of us
explicitly specifying what they should be. This is a very helpful
feature, but when designing programs, it is always a good idea to
provide explicit types for all of our definitions. Not only does it
help the compiler infer types in much more complicated situations, but
it also helps you, the programmer, in thinking about how your program
is structured. We can do this using a *type signature*. Assume that
we have the following definitions in a file.

```
root2 = sqrt 2
cube x = x ** 3
multiply a b = a * b
```

To add type signatures to these definitions, all we need to do is add a line just above each one like so.

```
root2 :: Double
root2 = sqrt 2
cube :: Double -> Double
cube x = x ** 3
multiply :: Double -> Double -> Double
multiply a b = a * b
```

The `::`

symbol means that this is a type signature, and can be
read as *has type*. So the first type signature can be read as
*root2 has type Double*.

For the second definition, the type signature isn’t just a single
type, because `cube`

is a function. Functions are represented in
type signatures using an arrow `->`

similar to the arrow used in
lambda expressions. You can read the arrow here as *to*. This type
signature can be read as *cube has type Double to Double*.

The definition for `multiply`

is also a function, but it takes
two inputs instead of one. An arrow `->`

is used in the type
signature, not only between the input and output, but also between
each of the inputs. These extra arrows have a deeper meaning that will
be revealed later. You can read this type signature as *multiply
has type Double to Double to Double*, which is a funciton that takes
two values of type `Double`

, and outputs a value of type
`Double`

.

In your text editor, open the `Lambdas.hs`

file you created
earlier and add type signatures to each of the definitions.

```
add :: Double -> Double -> Double
add a b = a + b
square :: Double -> Double
square x = x * x
cuberoot :: Double -> Double
cuberoot a = a ** (1 / 3)
circumference :: Double -> Double
circumference radius = 2 * pi * radius
```

One last type you should know about before moving on to the next
section is `String`

, which is a sequence of characters, much like
this sentence you are reading right now. A character could be a
letter, a number, or a symbol. To construct a `String`

, surround
a sequence of characters with double quotes.

```
message :: String
message = "Welcome to Haskell Roguelike"
```