Syntax in Functions

Patterns

When defining functions in haskell, you can define separate function bodies for different patterns. This leads to code that is simple and readable. Pattern matching can be done on any data type - numbers, characters, lists, tuplets, etc.

The factorial' function defined recursively:

factorial' :: (Integral a) => a -> a
factorial' 0 = 1
factorial' n = n * factorial (n - 1)

Pattern matching can also fail when a function receives an unexpected input. When making patterns, you should always include a catch-all pattern that programs do not crash if we receive some sort of unexpected input.

Pattern matching can also be used on tuples. If we wanted to add together two vectors, we add their x components separately and then add the y components the same way after the x components have finished.

Adding vectors together using pattern matching:

addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a)
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)

Guards

Patterns are a way of making sure a value conforms to a set of rules, where as guards are a way of testing whether some property of a value (or several of them) are true or false (think if (true) { /* do something */} else { /*do something else*/ }) What separates guards apart from a regular js conditional is that guards are a lot more readable when you have several conditions and they play nicely with patterns.

Guards are indicated with an indent followed by a pipe. They follow a function's name and its parameters.

Guards are basically boolean expressions. If it evaluates to True, then the corresponding response is returned, if False, it move onto the next guard and evaluates it

Guards are used to create simple evaluation functions like min and max.

Here's a custom implementation of max:

max' (Ord a) => a -> a -> a
max' a b
    | a > b = a
    | otherwise b

Guards can also be written inline:

max' (Ord a) => a -> a -> a
max' a b | a > b = a | otherwise b

Don't do that. That's ugly and not very readable

Where bindings and let bindings

Case expressions

We can evaluate case expressions in Haskell by considering the possible cases of the value of a variable. Oh, and we can do pattern matching on case expressions too.

A pattern matching head function:

head' :: [a] -> a
head' [] = error "No head for empty lists!"
head' (x:_) = x

The same function using a case expression

head' :: [a] -> a
head' xs = case xs or [] -> error "No head for empty lists!"
                      (x:_) -> x

The syntax for case expressions is pretty simple:

case expression of pattern -> result
    pattern -> result
    pattern -> result
    ...

results matching ""

    No results matching ""