This is the tenth and last article of a series on the functional language Haskell for beginners

Thank you for joining us for the tenth and last part of our Haskell series, you will find the previous article here where I explain modules and exceptions.

In this article we are going to cover `Maybe`, `Just` and `Nothing` as an alternative to handling exceptions and errors.

## Data Type

But before jumping into the usage of `Maybe`, let's have a look at how we can create our own data types. We are going to rewrite the module we wrote previously for currency conversion:

``````-- This is CurrencyConverterB.hs

module CurrencyConverterB (
CurrencyRate (Rate),
convert
) where

data CurrencyRate = Rate String String Float

convert :: CurrencyRate -> Float -> Float
convert (Rate _ _ rate) amount = amount * rate
``````
``````-- This is Main.hs
import CurrencyConverterB

eurToUsd :: CurrencyRate
eurToUsd = Rate "eur" "usd" 1.12

usdToEur :: CurrencyRate
usdToEur = Rate "usd" "eur" 0.88

main = do
let eur = convert eurToUsd 10
putStrLn ("10 EUR = " ++ show eur ++ " USD")

let usd = convert usdToEur 10
putStrLn ("10 USD = " ++ show usd ++ " EUR")
``````

Ok let's go step by step, first the `CurrencyConvertB` file:

• Just like we saw previously, we use the `module` keyword to define the name of our module and what we want to export out of it.
• You will note one subtlety with `CurrencyRate (Rate)` in the `module`, this is because of our data type which we created called `CurrencyRate`. `Rate` is the name of the constructor, sometimes developers use the same name for both type and constructor. In order to clarify the difference here I used different names.
• Now our type `CurrencyRate` is composed of three things: a `String`, another `String` and a `Float` so that we can keep the base currency, the target currency and the exchange rate.
• Finally we create a simple `convert` method which takes a `CurrencyRate` and an amount. Then it will simply multiply this amount with the exchange rate. You will note that when using `data` to create new types, the only way to access fields is through pattern matching. I recommend that you look into "records" to make this part easier, especially if you need more fields.

Now that we understand this module, let's have a look at our new `Main`:

• First we import our module `CurrencyConvertB`.
• Next we define two functions which uses our `Rate` constructor to create new `CurrencyRate`. The syntax is pretty simple: `ConstructorName field field`.
• Then we call our `convert` method using the rates we defined above and get the same results as our previous code.

Let's run it in GHCI:

``````ghci> :l Main
[1 of 2] Compiling CurrencyConverterB ( CurrencyConverterB.hs, interpreted )
[2 of 2] Compiling Main             ( Main.hs, interpreted )
ghci> main
10 EUR = 11.2 USD
10 USD = 8.8 EUR
``````

Neat, everything gets automatically compiled based on the `Main`'s imports. Note that you can also compile it and run it like so:

``````➜  ghc --make Main.hs
[1 of 2] Compiling CurrencyConverterB ( CurrencyConverterB.hs, CurrencyConverterB.o )
[2 of 2] Compiling Main             ( Main.hs, Main.o )
➜  ./Main
10 EUR = 11.2 USD
10 USD = 8.8 EUR
``````

## Maybe

Now, to answer the question: "Why did we learn about data types before Maybe ?"

It is because `Maybe` would probably look something like this:

``data Maybe a = Just a | Nothing``

A few things to note:

• The definition of `Maybe` is parameterized with a type variable `a` so we can use it with any type we want.
• `Maybe` has two possible constructor: `Just a` or `Nothing` . When creating a new data type you may add different constructors and separate them with a pipe `|`.

The idea behind `Maybe` is mainly to check for the presence of a value, if you want to compare it to some other languages it is similar to: "This function returns a user or null". So translated to Haskell it would be: "My function returns Just a user or Nothing".

Let's look at some simple code to understand of usage of `Maybe`:

``````-- this is maybe.hs
import Data.List

main = do
let a = [1, 2, 3, 4, 5]
let result = find (<5) a
putStrLn (show result)
``````

This is a very typical example, we are loading the standard module `Data.List` to use the find function. I copied the definition below:

The `find` function takes a predicate and a structure and returns the leftmost element of the structure matching the predicate, or `Nothing` if there is no such element.

Let's verify this:

``````ghci> :l maybe.hs
[1 of 1] Compiling Main             ( maybe.hs, interpreted )
ghci> main
Just 1
``````

Indeed, we have `Just` the first element of the list, being 1. Now let's change the code from `<5` to `>5` and recompile:

``````ghci> :l maybe.hs
[1 of 1] Compiling Main             ( maybe.hs, interpreted )
ghci> main
Nothing
``````

This time we get `Nothing`.

Now, let's try to programmatically handle both cases, we will add a few lines to our code in maybe.hs:

``````-- this is maybe.hs
import Data.List

main = do
let a = [1, 2, 3, 4, 5]
let result = find (<5) a
case result of
Nothing -> putStrLn "Sorry, could not find what you were looking for"
Just b -> putStrLn ("Found your " ++ show b)
``````

We used the same method with a `case` statement as in our try example in our previous article. Now let's recompile and run it:

``````ghci> :l maybe.hs
[1 of 1] Compiling Main             ( maybe.hs, interpreted )
ghci> main

Let's change again the `<` sign:

``````ghci> :l maybe.hs
[1 of 1] Compiling Main             ( maybe.hs, interpreted )
Ten down ! It took me more than 6 months but we are finally there, 10 articles to introduce important concepts of Haskell to get beginners started in this hidden gem of a language. There are still many concepts to discover such as: `Functor`, `Monoid`, `Monad` and so on. If you want to continue your Haskell experience, I encourage you to subscribe to Haskell Weekly newsletter to get interesting content every week. Until then, good luck in your learning adventure !