Haskell Course - Lesson 3 - Numbers

We'll study numbers first because they are one of the most useful types in Haskell. After this lesson, you'll understand 4 new types and learn how to use Haskell as your personal calculator. 🤓

Common numeric types in Haskell

Not all numbers are the same. And in Haskell, we have four different numeric types: Int, Integer, Float, and Double.

Int and Integer

Both Int and Integer are types that represent whole numbers (i.e., 3 can be an Int or Integer, but 3.2 can't).

The difference between Int and Integer is the size of the numbers that it can store. Integer can hold numbers as big or small as your computer can handle. But Int has a maximum value of 263 (that's 2x2x2x2x2... 63 times 👀, big enough for most cases, if you ask me) and a minimum value of -263.

I assume that you can do the math in your head to know how big is that number.

Just kidding 🤣 , we can ask Haskell to do the math for us. Open ghci in your terminal (like we saw in lesson 1), write 2^62, and hit enter:

2^62  -- This will give you: 4611686018427387904

Haskell calculates the number for us! Awesome! Now, let's indicate that this number "has type of" Int and try again:

2^62 :: Int  -- This will also give you: 4611686018427387904

So far, so good. Now, let's try with a bigger number. Let's say 264:

2^64 :: Int  -- Oh no! This will give you: 0! 👀

You can try with larger numbers, too! As you can see, numbers greater than 263 are too big for Int and are lost. But, if we try one of those numbers as Integer, we get the correct result:

2^69 :: Integer  -- This will give you: 590295810358705651712 😏

There you go! 😎 No more unexpected zeroes.

So, why do we need Int if Integer can do the same and has no limits? Because Int is more efficient. The program runs faster if we use Int.

What does all this mean to you?

  • If you know you're going to work with small (smaller than ±263) whole numbers, use Int. Else, use Integer.
  • If a function returns an Int or Integer, you can be sure that it'll be a whole number.

But what about the rest of the numbers? What about numbers with decimal point (with fractional value) like 4.5?

Float and Double

Both Float and Doube are real

floating-point numbers
. They are types that represent real numbers, whole and fractional (i.e., 4.7 or 6.001).

The difference is the level of precision that they have. Float has

single precision
, and Double has (you guessed it) double the Float's precision.

Theoretically, the reasons as to when to use one or de other are somewhat analogous to the Int and Integer cases. Double has double the precision but hogs more memory because it uses twice as many bits to represent numbers.

Recommendation based on real-world use: Don't use Float. Use Double. There's rarely a speed disadvantage in modern computers, and with Double, you are much less likely to shoot yourself in the foot with rounding errors.

Let's see what happens if I want to show the first 20 digits of pi (π) in ghci:

3.14159265358979323846 :: Float  -- Result: 3.1415927

With Float, I get 7 digits after the point.

3.14159265358979323846 :: Double  -- Result: 3.141592653589793

With Double I get 15 digits after the point (double the previous precision).

And what if I don't specify the type?

3.14159265358979323846  -- Result: 3.141592653589793

Haskell assumes that you want the best precision possible and infers that you want to use a Double.

Ok. Those are Haskells standard numeric types. Now let's do some simple calculations!

Doing some simple calculations

Here are a few math operations in Haskell and its correspondent symbol and example:

OperationHaskell SymbolExample
Addition+3 + 2
Subtraction-3 - 2
Multiplication*3 * 2
Division/3 / 2
Exponential^4 ^ 3

Remember that operations have an order (division before addition and such). And in Haskell—the same as in maths—you can alter the order by applying parenthesis:

  • 6 + 4 / 2 = 8

  • (6 + 4) / 2 = 5

Now, we can use ghci as our personal calculator.

Calculating the volume of a cube

The formula to calculate the volume of a cube is volume = side3. This means that to obtain the volume of a cube, we just need to calculate the cube of its side. If we have a cube with 2 meters (2m) of side length, the volume of the cube will be: side3 = 23 = 8.

And to calculate the volume of a cube of side length 3m, we have to write:

3^3  -- That will give me a volume of  27m3

Note: You can navigate through everything you executed in ghci using your arrow keys! Up goes back to previous expressions, and down goes forward to newer expressions.

Ok, that was the warm-up.

8^3 = 512m3

I know, I know. That was too easy. Let's do something more interesting.

Increasing the difficulty

I'll provide the expression in the form of a sentence, and you have to translate it into a valid Haskell expression in GHCi and check the result:

(22-13)/3 = 3.0

12/4 + 4^2 = 19.0

3^9 - 943*500 = -451817

Notice that Haskell returns the first and second results as a floating-point number (.0) even if the results are whole numbers. But, in the last one, Haskell returns a whole number (without .0). Why is that?

Because Haskell knows (before calculating the result) that if you add two whole numbers, the result will always be a whole number. Same with subtraction and exponential. But there are many cases when a division of whole numbers gives you fractional numbers (i.e., 3/2 gives you 1.5). So, Haskell makes sure that the division never fails by transforming the numbers to Float or Double before dividing.

We'll learn the specifics of how Haskell does this in the "Type classes" lesson.

Ok, we're going to stop here. But you're not done yet! Make sure to complete this week's homework! See ya in the next lesson! 💪😄

Homework

  1. Get familiar with the order of operations and take a peek at the programming languages section.

2. Fahrenheit to Celsius

Celsius (ºC)—also referred to as centigrade—is the most common non-scientific unit of temperature. But, the US still uses Fahrenheit (ºF). Let's say that you have friends in the US and, when chatting, they always comment about their temperature in Fahrenheit. You got tired of doing the math in your head, and you decide to use Haskell.

This is the formula to transform from Fahrenheit to Celsius: Tc = (Tf - 32)*5/9. Where Tc is the temperature in Celsius (the result) and Tf is the temperature in Fahrenheit. Using only ghci transform the temperatures to Celsius:

  • How many ºC is 100 ºF?
  • How many ºC is 32 ºF?
  • How many ºC is 212 ºF?

You are doing great! With each lesson, you get closer and closer to becoming a full-fledged programmer! 🔥 Next lesson, we'll learn about characters, lists, and Strings! See you there! 😄

PD: If you find this course valuable, please share it so more people can learn! 😄