# Haskell Course - Lesson 8 - Intro to Type classes

Many beginners struggle with type classes. That's because it's a more abstract concept than the ones we have learned so far. But don't worry. We'll see many examples and repeat our reasoning in different circumstances to hone in on the intuitive understanding of the concepts. Hope you like it! 😄

First of all, let's set things straight. You said that functions are used by writing first their name and then their parameters separated by spaces. So, how come the `==` and others like this have one parameter before their name and one after?

— The guy that sits in the front row in every class.

Sorry, I overlooked that in the last lesson 😅. Sure, let's see prefix and infix functions first!

## Prefix and Infix functions

I'll probably move this section to the functions lessons in the future.

Prefix and infix are the two ways of calling (using) functions.

Because we don't like to waste time over here, we'll learn these concepts while using a new native function: `elem`. The `elem` function takes a value and a list of values of the same type and returns `True` if the value is inside the list and `False` if it isn't.

### Prefix functions

Prefix functions are called writing, first their name and then their parameters separated by spaces. For example:

``````elem 3 [1,2,3]   -- True
elem 3 [1,2]     -- False
``````

If a function's name has letters and numbers, it's considered a prefix function by default.

### Infix functions

Infix functions are called by writing their name sandwiched between their parameters. Like the `+` function:

``````2 + 3  -- 5
``````

If a function's name has only special characters ( `+`, `/`, `=`, and such), it's considered an infix function by default.

We use them differently, but it's not that infix functions are special. In fact, we can easily use a prefix function as an infix function using the infix notation.

### Infix notation

To use a prefix function like an infix function, we just have to surround its name with backticks:

``````3 `elem` [1,2,3] -- True
3 `elem` [1,2]   -- False
``````

You could write prefix functions with more than two parameters as infix functions. But I advise against it since you have to add extra parenthesis, and it doesn't read nicely at all! 😵‍💫

There's also a way to do the inverse (infix to prefix) using the prefix notation.

### Prefix notation

To use an infix function like a prefix function, we just have to surround its name with parenthesis:

``````(+) 2 3      -- 5

(==) 'a' 'b' -- False
``````

It looks less intuitive in these cases. But it's useful in certain circumstances that we may encounter in this course.

OK, with that out of the way, we can see what the heck type classes are.

This is an introduction to type classes, so we won't learn how to create type classes nor make a type an instance of a type class. The objective of this lesson is to understand what they are so we can use the native type classes that come with Haskell.

## Type Classes

If you search for "class" or "classes" as a programming concept, you could get more confused. Most responses will be about
object-oriented programming (OOP)
, and "class" in OOP is a different thing. Make sure to add the "type" and "Haskell" keywords to your search!

Type classes are interfaces that define some behavior. They are like clubs that types can belong to if they have what it takes! 😈

If you meet a guy that belongs to the advanced-drawing club, you know that he can draw. Why? Because it's one of the requirements to enter the club!

Type classes are the same. They have particular behaviors (functions). If a type implements and supports the behaviors of a type class, then the type is an Instance of that type class (a member of that club). Let's explore a few examples:

## The `Eq` type class

The `Eq` type class is all about equality. The types that are instances of the `Eq` type class can say if two values of its type are equal or different by using the `==` (equal) and `/=` (not equal) functions.

Looking at the type signatures of `==` and `/=`, we can learn more:

``````(==) :: Eq a => a -> a -> Bool

(/=) :: Eq a => a -> a -> Bool
``````

The `=>` symbol is the `class constraint` symbol. As you guessed, it indicates that a polymorphic type is constrained to be an instance of a type class. (In this case, the type `a` has to be an instance of the type class `Eq`.) So, we're constraining (limiting) the types that you can pass to these two functions, from all the types to only those that are instances of the `Eq` type class.

It's like a bouncer that lets you in if you're a type that belongs to the `Eq` club.

How is this useful to you? Because you can use polymorphic types and still protect yourself from passing the wrong type. 😎 For example, imagine you create this function:

``````func x y = if x == y then x else y
``````

You don't do math, manipulate strings, or do anything type-dependent. So you can use type variables. But you do check if the values are equal. So you want to make sure that this function only accepts values that can be checked for equality. That's what the `Eq` type class is here for. To block you from using types with values that can't be compared.

Because `==` has the `Eq a` constraint and `func` uses `==` inside, our type signature automatically inherits that constraint:

``````func :: Eq a => a -> a -> a
``````

Remember the Booleans lesson? We used `==` and `/=` to compare values of type `Char`, `Int`, `String`, etc. That's because all those types are instances of the `Eq` type class. And Haskell already knows how to check if the values of all those types are equal or not.

So far, all the types that we encounter are instances of this class type (except for functions).

But, you can't do much with types that only belong to the `Eq` type class. You can only tell if they are the same exact value or not. Luckily, `Eq` is not the only club in town!

## The `Ord` type class

The `Ord` type class is all about order. The types that are instances of the `Ord` type class can order their values and say which value is the biggest.

For example, a type that is an instance of the `Ord` type class can use the `>` (greater than) function:

``````(>) :: Ord a => a -> a -> Bool
``````

We've already used this function in previous lessons. It takes two values of the same type and returns a boolean:

``````4 > 9 -- False
``````

How are the values ordered? It depends on the type. With numbers, it follows the mathematical order (e.g., `4` comes before `5` and after `3`). With characters, it follows the Unicode order (like we discussed here). And other types have other rankings.

As you can see, each type has its own way of implementing the behaviors (functions) of the type class. And the type class doesn't care, as long as they have them. It makes sense because each type has its own quirks, and a single definition of `==` or `>` can't possibly fit them all.

We'll learn how to implement our own instances in future lessons.

They may look similar, but`Ord` is on an entirely different level than `Eq`. Because for `>` to be effective, the type has to have some sort of ranking. A way to tell if something is greater than another thing. And this opens the doors to many other functions that derive from this capacity. i.e., all the operators that do inequality testing, `compare`, `max`, and `min` functions.

We already know how to use inequality operators, so let's dive into the other functions.

### The `min` and `max` functions

The `min` function takes two values of a type that is an instance of `Ord` and returns the minimum of the two:

``````min :: Ord a => a -> a -> a
``````

Example:

``````min 12 19 -- 12
``````

The `max` function takes two values of a type that is an instance of `Ord` and returns the maximum of the two:

``````max :: Ord a => a -> a -> a
``````

Example:

``````max 12 19 -- 19
``````

And finally, the compare function.

### The `compare` function

Check out the `compare` type signature:

``````compare :: Ord a => a -> a -> Ordering
``````

The `compare` function takes two values of a type that is an instance of `Ord` and returns a value of type `Ordering`, indicating the order of the values.

Type what?

This is a new type for us. In the same way that `Bool` has only two values (`True` and `False`), the `Ordering` type has only three values: `LT` (lesser than), `EQ` (equal), and `GT` (greater than).

Example:

``````compare 4 9         -- LT (4 is lesser than 9)

'f' `compare` 'e'   -- GT ('f' is greater than 'e')

True `compare` True -- EQ ( True is equal to True)
``````

Because there's not much we can do with values of the `Ordering` type, compare isn't used as frequently as the other functions.

Again, so far, all the types we learned are instances of this class type (except for functions).

Now, you might say:

If I can check `EQ` with the `Ord` type class, why do I need the `Eq` type class?

Because you have to learn how to doodle before you can learn how to draw.

## Doodling before drawing

Sometimes a type has to first be an instance of one type class to be allowed to become an instance of another. Like you have to belong to the doodling club to be allowed to apply to the drawing club.

That's the case with `Eq` and `Ord`.

To order values of a type, for starters, you have to be able to tell if they are equal or not. This tells us that if we have a type that is an instance of `Ord`, it also supports all the `Eq` behavior!

Numbers are a similar case.

## Numbers

Numeric types are one of the most used types in any programming language. But not all numeric types can do the same thing, so let's learn about their type classes.

We'll start with the most popular club of all: The `Num` type class.

### The `Num` type class

The types that are instances of the `Num` type class can behave like numbers. But not like a specific subset of numbers. The `Num` type class defines the behavior of numbers in general.

For example, types that are instances of this type class can be (among other things) added, subtracted, or multiplied:

``````(+) :: Num a => a -> a -> a

(-) :: Num a => a -> a -> a

(*) :: Num a => a -> a -> a
``````

For example:

``````5 - 1      -- 4

8.9 + 0.1  -- 9.0

'a' - 'b'  -- ERROR! Char is not an instance of Num!
``````

Now we're talking! This is a life savior! Imagine I want to create a function that does some math:

``````add1 x = x + 1
``````

I don't want to choose a type like `Int` and only allow `Int` values. `Float`, `Double`, and `Integer` types could work perfectly fine! But, if there were no constraints, I could pass any type! What's the result of `'a' + 1`? Or `True + 1`? It doesn't make any sense!

Because only types that are instances of the `Num` type class can use `+`, and because `Float`, `Double`, `Int`, and `Integer` are all instances of `Num`, we can constraint our function like this:

``````add1 :: Num a => a -> a
``````

Now, we can be sure that if Haskell doesn't complain when we use our function, we're safe.

Not only that, we don't even have to manually specify the constraint! If you create that `add1` function in GHCi and check the type, you'll get the exact same type signature by default! Haskell knows that to use `+`, you have to be an instance of the `Num` type, so it infers a type signature for `add1` that blocks any other type from using it. Thanks, Haskell! We love you, you little nerd! 🤓

This is awesome! But, sometimes, we need something more specific.

### The `Integral` type class

By now, you know the drill. The `Num` type class includes all the numbers, and the `Integral` type class only the whole (or integral) numbers. Such as `4`, but not `4.3`.

`Integral` is a more exclusive club than `Num`. Of all the types we studied so far, only `Int` and `Integer` belong to it.

This type class defines many behaviors, one of the most well-known `Integral` functions is `div`.

``````div :: Integral a => a -> a -> a
``````

It takes two values of a type that is an instance of `Integral` and divides them, returning only the whole part of the division.

Examples:

``````3 `div` 5    -- 0

div 5 2      -- 2
``````

Now, this doesn't mean that `Foat` and `Double` only hang out in the `Num` club. In fact, they have their own club!

### The `Fractional` type class

The `Fractional` type class is all about fractional numbers. The types that are instances of the `Fractional` type class can represent and modify fractional values.

By far, the most valuable function that instances of the `Fractional` type class can use is `/`:

``````(/) :: Fractional a => a -> a -> a
``````

The all-mighty division. Unlike `div`, we can be more precise about our values because we're using fractional numbers. For example:

``````10 / 5  -- 2.0

5  / 2  -- 2.5

10 / 3  -- 3.3333333333333335
``````

Which reminds me, what about the function we created to transform from Fahrenheit to Celsius? 🤔

``````fToC x = (x - 32)*5/9
``````

It takes a value and returns a value.

``fToC :: a -> a``

The value that it takes must be a numeric type (we're doing math with several mathematical functions).

``fToC :: Num a => a -> a``

But not any numeric type will do! It has to be a type that can be divided using `/`.

``fToC :: Fractional a => a -> a``

At the end of the day, the most restrictive constraint wins.

Until now, we've been restricting if the type is an instance of a particular type class. And we know that there can be more specialized type classes (`Fractional` is a more specialized type class than `Num`). But what if you need a type that can both draw AND play basketball?

## Multiple constraints

Applying constraints is more flexible than it seems. Sometimes you need different constraints for different type variables. Or the same type variable with multiple constraints. All this can be easily expressed in Haskell.

### Multiple constraints for the same type variable

Take this function that skips the number 3:

``````skip3 x = if x == 3 then x+1 else x
``````

The `x` can be of any type that is an instance of `Eq` (because of `==`) and `Num` (because of `+`). To specify multiple constraints for the same type variable, we have to surround them with parenthesis and add a comma between them. Like if they were a tuple:

``````skip3 :: (Eq p, Num p) => p -> p
``````

Now the `p` type variable has to be a type that's an instance of both `Eq` and `Num`. We could add more constraints if needed.

### Constraints for multiple type variables

Let's create a function that takes two values and returns `1` if the first value is greater than the second, and `0` otherwise. (In

binary
, `1` usually means `True` and `0` means `False`).

``````isXBigger x y = if x > y then 1 else 0
``````

In this case, `x` and `y` have to be instances of `Eq`. And the return value is a number of an unspecified type, so it's an instance of `Num`. Putting this together, the type signature will be:

``````isXBigger :: (Ord a, Num p) => a -> a -> p
``````

``````mistery1 x y z = if x > y then z/2 else z
``````

We compare `x` and `y`, so they have to be instances of `Ord` type class. And the return value it's divided using `/` in one of the if-else paths. So `z` has to be an instance of `Fractional`.

``````mistery1 :: (Ord a, Fractional p) => a -> a -> p -> p
``````

Finally, our last example is a modification of `mistery1` where we add `1` to `x` before comparing it to `y`:

``````mistery2 x y z = if x+1 > y then z/2 else z
``````

Same as before. But now `x` and `y` also have to be an instance of `Num` to be able to use `+`.

``````mistery2 :: (Ord a, Num a, Fractional p) => a -> a -> p -> p
``````

As you can see, we can apply as much constraints as needed. Of course, Haskell will apply them for you (most of the time). And you'll have to correctly interpret and understand them.

There are tons of type classes and behaviors that we didn't cover today, but don't worry about it until you cross paths with them. It's no use to memorize a bunch of behaviors and type classes if you don't actively work with them.

I hope that, by now, you feel comfortable reading—and appreciating the value of—type constraints. To help you with that, I've prepared some questions. 😬

## Homework

### Type signature practice

Guess the type signature of `func` without using GHCi:

``````func a b = if a > 18 then "You can pass, " ++ b else "Sorry, " ++ b ++ ". Too young!"
``````
``func :: (Ord a, Num a) => a -> [Char] -> [Char]``

`a` has to be an instance of `Ord` to use `>` and `Num` to be compared to a number.

Which function is more type-restrictive?

``````func1 x y = x*2 + y

func2 x y = x/2 + y

func3 x y = x `div` 2 + y
``````
``func1 :: Num a => a -> a -> a``
``func2 :: Fractional a => a -> a -> a``
``func3 :: Integral a => a -> a -> a``

`func1` is the less restrictive of the three, because all native numeric types are accepted. `func2` and `func3` are equally restrictive because each can accept only two native numeric types.

Last question:

``fromIntegral :: (Integral a, Num b) => a -> b``

### Install VSCode

We'll need a text editor for our next lesson. You can use whichever you want, but if you haven't coded before, I recommend VSCode.

I won't explain step-by-step how to install a program as popular as VSCode. But I'll tell you exactly what we need, and you'll have to figure it out. Like a proper software developer!🕵️

We need:

• VSCode.
• Two VSCode extensions: