Resources
Notes
- Pattern matching is used for deconstruction and binding
- You can pattern match in list comprehensions if you want
where
- serve as deconstructors / binders / helpers that would normally written first in an imperitive language
- scoped to the entire function
- can be nested. It’s a common idiom to make a function and define some helper function in its where clause and then to give those functions helper functions as well, each with its own where clause.
- is bound to a surrounding syntactic construct, like the pattern matching line of a function definition
- can be multiple lines each defining the same thing, as these lines will pattern match
let <bindings> in <expression>
- scoped to the entire function, not including guards
- let … in … is an expression, that is, it can be written wherever expressions are allowed.
- puts the bindings first and the expression that uses them later whereas
where is the other way around
- Has crazy scoping rules
- Automatically fills list comprehensions
- Applies globally if not defined with an
in
- Can be applied locally to only certain expressions
let boot x y z = x * y + z in boot 3 4 2
- (which is why it doesn’t scope to guards)
- Guards
- If all the guards of a function evaluate to False (and we haven’t provided an otherwise catch-all guard), evaluation falls through to the next pa`ttern
case expression of pattern -> result
- Called case expressions because they’re expressions
- Recursion
- Use the base cases to build the construct you need
- For example, the base cases contain the empty list that you append everything to
- The edge condition, as is most of the times with lists, is the empty list
- Recursion almost always does something with the head, and if the condition isn’t fulfilled, calls itself again on the tail
- Higher order functions
- If our function requires us to pass it a function that takes only one parameter, we can just partially apply a function to the point where it takes only one parameter and then pass it.
- The most common use case with flip is calling it with just the function parameter and then passing the resulting function on to a map or a filter.
- use lambdas in this way when you want to make it explicit that your function is mainly meant to be partially applied and passed on to a function as a parameter.
- Partial application is everywhere. Always check whether you need to specify a parameter
- if you have a function like
foo a = bar b a you can rewrite it as foo = bar b, because of currying.
- folds are, along with maps and filters, one of the most useful types of functions in functional programming.
- scan is a progressing fold
- use takeWhile to cut the scanlist off at the first occurence of a sum greater than 1000.
- map function application over a list of functions.
- map ($ 3) [(4+), (10*), (^2), sqrt]
- “Raking over the coals”
- Good signature:
(.) :: (b -> c) -> (a -> b) -> a -> c f . g = \\x -> f (g x)