In the previous article we learned how to represent a problem by using algebraic data types.

In this article I will talk about *functions*, *purity*, *lazyness*, *type signatures* and some
tools like *partial application* and *pattern matching*.

### Functions

Functions are the base of functional languages.
In Haskell they receive 0 or more arguments and **always** return a value.
Haskell syntax for functions is really simple:

numCardsInAPokerDeck = 53 numCards deck = length deck isAPokerDeck deck = (numCards deck) (==) numCardsInAPokerDeck biggerDeck d1 d2 = if (numCards d1) > (numCards d2) then d1 else d2

Function application is left associative.

### Purity

Haskell functions are *pure*. This means that they cannot alter the state of the program by
producing *side-effects*.
Any *pure* function is also idempotent so it must return always the
same result for a given set of arguments.

How does Haskell achieve purity?
- *There are no variables*:
Functions can be used to define contant values but those can't be modified.
- *Immutable data types*:
All the builtin data types defined in Haskell are immutable.
Instead of altering the state of an instance, copies representing the new one are returned.

### Lazyness

Since functions are *pure* and hold no *side-effects* the computation can be performed at any time.
This property allows programs to evaluate the code only when the result is needed.

dontEvaluateSecondParam a b = if True then a else b powerOfTwo val = foldl (*) 1 (take val (repeat 2)) dontEvaluateSecondParam "foo" (powerOfTwo 10000) -- "foo"

### Type signatures

Haskell can infer function's *type signatures* most of the times, although, is good to document
all of them by providing the arguments and the return types.

You can learn a lot just by reading a function's *type signature*.
For instance, imagine you want a function that takes a list and returns wether the list is empty or not.
You can use Hoogle and search for `[a] -> Bool`

, how cool is that!?

numCardsInAPokerDeck :: Int numCardsInAPokerDeck = 53 numCards :: Deck -> Int numCards deck = length deck isAPokerDeck :: Deck -> Bool isAPokerDeck deck = (==) (numCards deck) numCardsInAPokerDeck

Types signatures declarations are right associative!

So far, so good. But then, how can you define a function that takes more than one argument?
The answer is simple and astonishing: you can't, *Haskell functions can only take one argument*.
Fasten your belts, we are about to enter to higher order function nirvana!

### Partial application

Haskell functions are considered *Higher Order Functions*. This means that a function can:

- Take a function as an argument
- Return a function

This feature is used to do partial application. Imagine you have a function that takes two numbers and adds them:

add' :: Int -> (Int -> Int) add' a b = a + b add' 2 3 -- 5

In Haskell you don't have multiple arguments, instead you use partial application. For instance, the
`add'`

function we just defined can be defined as "a function that takes a number, returns a
function that takes another number and returns the addition of both". Inception!

Remember that *type signatures* are right associative. The previous one could be simplified:

add' :: Int -> Int -> Int add' a b = a + b addTwo = add' 2 addTwo 3 -- 5

Now that we know how partial application works, we can now add some type signatures to our previous examples:

biggerDeck :: Deck -> Deck -> Bool biggerDeck d1 d2 = if (numCards d1) > (numCards d2) then d1 else d2 firstDeck :: Deck firstDeck = take 5 (repeat Joker) secondDeck :: Deck secondDeck = take 2 (repeat (Card Spade NA)) biggerThanFirstDeck :: Deck -> Bool biggerThanFirstDeck = biggerDeck firstDeck biggerThanFirstDeck secondDeck -- firstDeck biggerDeck firstDeck secondDeck -- firstDeck

### Pattern matching

Last tool I'm going to explain on this article is *pattern matching*.

Imagine we want a function that takes a `PlayingCard`

as an argument and returns wether its a
Joker or its not:

isJoker :: PlayingCard -> Bool isJoker Joker = True isJoker a = False

We can use `_`

if we don't need to assign the value:

isJoker :: PlayingCard -> Bool isJoker Joker = True isJoker _ = False isJoker Joker -- True isJoker (Card Spades NA) -- False

We can "deconstruct" the values to match only certain parts:

isSuite :: Suite -> PlayingCard -> Bool isSuite suite Joker = False isSuite suite Card s n = suite == s isDiamond = isSuite Diamond isHeart = isSuite Heart isSpade = isSuite Spade isClub = isSuite Club isDiamond Joker -- False isDiamond Card Diamond N3 -- True isDiamond Card Club N7 -- False

We can even "deconstruct" lists and tuples!

getFirstCard :: Deck -> PlayingCard getFirstCard [] = error "OMG! The deck is empty!" getFirstCard x:xs = x isPair :: (PlayingCard, PlayingCard) -> Bool isPair (Joker, b) = True isPair (a, Joker) = True isPair (a, b) = a == b