Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Programming for "Dummies"

scato
July 05, 2017

Functional Programming for "Dummies"

Should have been called: An impractical introduction to Haskell for experienced PHP developers.

scato

July 05, 2017
Tweet

More Decks by scato

Other Decks in Technology

Transcript

  1. Referential Transparency An expression is referentially transparent if you can

    replace that expression with its corresponding value without changing the behavior of the program.
  2. Referential Transparency function main() { $i = 41; $j =

    $i + 1; // <- evaluates to 42 return $j; }
  3. Referential Transparency Referential transparency means that when you read code,

    you only have to think of the outcome of an expression. You can forget about state, and the way that evaluating an expression can change that state.
  4. Immutability function average($a, $b) { $total = 0; $total +=

    $a; // <- fail! $total += $b; // <- fail! return $total / 2; }
  5. Immutable Data Structures $x = 1; $y = 2; $p

    = [0, 2]; $p[2] = 5; // <- fail
  6. Immutable Data Structures $xs = [1, [2, [3, null]]]; head($xs)

    // <- 1 tail($xs) // <- [2, [3, null]] $empty = null;
  7. Recursion function length($xs) { $length = 0; foreach ($xs as

    $x) { $length += 1; // <- fail! } return $length; }
  8. Recursion function sum($xs) { $sum = 0; foreach ($xs as

    $x) { $sum += $x; // <- fail! } return $sum; }
  9. Recursion function sum($xs) { if ($xs === null) { return

    0; } return head($xs) + sum(tail($xs)); }
  10. Recursion (1 + sum(tail([1, [2, [3, null]]]))) / (1 +

    length(tail([1, [2, [3, null]]])))
  11. Recursion (1 + sum(tail([1, [2, [3, null]]]))) / (1 +

    length(tail([1, [2, [3, null]]])))
  12. Recursion (1 + 2 + 3 + sum(null)) / (1

    + 1 + 1 + length(null))
  13. Recursion (1 + 2 + 3 + sum(null)) / (1

    + 1 + 1 + length(null))
  14. Recursion function sum($xs) { if ($xs === null) { return

    0; } return head($xs) + sum(tail($xs)); }
  15. Recursion function sum($xs) { if ($xs === null) { return

    0; } return head($xs) + sum(tail($xs)); // <- recursion }
  16. Recursion function sum($xs, $start) { if ($xs === null) {

    return $start; } return sum(tail($xs), head($xs) + $start); // <- tail recursion }
  17. Higher Order Functions A higher order function is a function

    that accepts a function as one of its parameters and/or returns a function.
  18. Higher Order Functions function sum(xs) { if (xs === null)

    { return 0; } return head(xs) + sum(tail(xs)); }
  19. Higher Order Functions const sum = xs => xs ===

    null ? 0 : head(xs) + sum(tail(xs));
  20. Higher Order Functions const add = x => y =>

    x + y; add(1)(2) // <- evaluates to 3
  21. Higher Order Functions const add = x => y =>

    x + y; add(1) // <- evaluates to y => 1 + y
  22. Higher Order Functions const add = x => y =>

    x + y; add(1) // <- partial application
  23. Higher Order Functions const add = x => y =>

    x + y; add(1) // <- higher order function
  24. Higher Order Functions const add = x => y =>

    x + y; const sum = xs => xs === null ? 0 : add(head(xs))(sum(tail(xs)));
  25. Higher Order Functions const foldr = f => z =>

    xs => xs === null ? z : f(head(xs))(foldr(f)(z)(tail(xs)))
  26. Higher Order Functions const foldr = f => z =>

    xs => xs === null ? z : f(head(xs))(foldr(f)(z)(tail(xs))) const sum = xs => xs === null ? 0 : add(head(xs))(sum(tail(xs)));
  27. Higher Order Functions const foldr = f => z =>

    xs => xs === null ? z : f(head(xs))(foldr(f)(z)(tail(xs))) const sum = xs => xs === null ? 0 : add(head(xs))(sum(tail(xs)));
  28. Higher Order Functions const foldr = f => z =>

    xs => xs === null ? z : f(head(xs))(foldr(f)(z)(tail(xs))) const sum = xs => xs === null ? 0 : add(head(xs))(sum(tail(xs)));
  29. Higher Order Functions const foldr = f => z =>

    xs => xs === null ? z : f(head(xs))(foldr(f)(z)(tail(xs))) const sum = xs => xs === null ? 0 : add(head(xs))(sum(tail(xs)));
  30. Higher Order Functions const foldr = f => z =>

    xs => xs === null ? z : f(head(xs))(foldr(f)(z)(tail(xs))) const sum = foldr(add)(0);
  31. Higher Order Functions const map = f => xs =>

    xs === null ? null : [f(head(xs)), map(f)(tail(xs))]; const compose = f => g => x => f(g(x)); // <- functional composition const constant = x => y => x;
  32. Pointfree Programming const sum = foldr(add)(0); const ones = map(constant(1));

    const length = compose(sum)(ones); // not one single parameter
  33. Pointfree Programming Topology (a branch of mathematics) works with spaces

    composed of points, and functions between those spaces. So a pointfree definition of a function is one which does not explicitly mention the points (values) of the space on which the function acts.
  34. Algebraic Data Types Just like there are rules for manipulating

    numbers, there are rules for manipulating types.
  35. 1. Sum Types 2. Product Types 3. Type Constructors 4.

    Recursive Type Definitions 5. Pattern Matching
  36. Sum Types data Bool = True | False not ::

    Bool -> Bool not True = False not False = True
  37. Product Types data Point = Point Int Int translate ::

    Point -> Point -> Point translate (Point dx dy) (Point x y) = Point (x + dx) (y + dy)
  38. Type Constructors data Maybe a = Nothing | Just a

    isNothing :: Maybe a -> Bool isNothing (Just a) = False isNothing Nothing = True
  39. Recursive Type Definitions data List a = Nil | Cons

    a (List a) length :: List a -> Int length Nil = 0 length (Cons x xs) = 1 + length xs
  40. Pattern Matching translate (Point dx dy) (Point x y) =

    Point (x + dx) (y + dy) length Nil = 0 length (Cons x xs) = 1 + length xs
  41. Hindley-Milner Type System The Hindley-Milner Type System is a system

    that allows you to do type inference on lambda calculus, in order to derive the most generic type of every expression in a program.
  42. Type Inference data List a = Nil | Cons a

    (List a) -- length :: List a -> Int length Nil = 0 length (Cons x xs) = 1 + length xs
  43. Type Inference data List a = Nil | Cons a

    (List a) -- length :: List a -> Int length Nil = 0 length (Cons x xs) = "1" ++ length xs -- <- oops -- No instance for (Num [Char]) arising from the literal ‘0’
  44. Type Inference data List a = Nil | Cons a

    (List a) length :: List a -> Int length Nil = 0 length Cons x xs = "1" ++ length xs -- <- oops -- Couldn't match expected type ‘Int’ -- with actual type ‘[Char]’
  45. Type Inference data List a = Nil | Cons a

    (List a) length :: List a -> Int length Nil = 0 length Cons x xs = length -- <- totale nonsense -- Couldn't match expected type ‘Int’ -- with actual type ‘List a0 -> Int’
  46. Type Inference the algorithm (roughly): 1. assign type variables to

    all expressions (both left and right of an ‘=’) 2. start at the top 3. move to the next piece of code that imposes a constraint 4. unify the two type variables 5. go back to step 3, until you reach the bottom
  47. Type Inference constraints: • the left and right hand side

    of ‘=’ must have the same type • the result of ‘+’ has the same type as the expressions on either side • applying a function with type a0 -> a1 is only valid on a parameter of type a0 • applying a function with type a0 -> a1 always produces a result of type a1
  48. Type Inference unifying type variables: • if a0 = Int

    and a1 = a0 then a1 = Int • if a2 = Maybe Int and a3 = Maybe a4 and a2 = a3 then a4 = Int
  49. Monads Once you understand monads for yourself, you lose the

    ability to explain them to others. – Douglas Crockford
  50. The Maybe Functor class Functor f where fmap :: (a

    -> b) -> f a -> f b data Maybe a = Nothing | Just a instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
  51. The Maybe Functor isEven x = x `mod` == 0

    fmap isEven (Just 1) -- Just False fmap isEven Nothing -- Nothing
  52. The Maybe Functor isEven x = x `mod` == 0

    maybeEven = fmap isEven maybeEven (Just 1) -- Just False maybeEven Nothing -- Nothing
  53. Derp examples of categories: • Grp – a category with

    groups for objects and group homomorphisms as morphisms (see also group theory) • Set – the category whose objects are sets, and where functions form the morphisms
  54. The Maybe Functor -- fmap id = id instance Functor

    Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
  55. The Maybe Functor -- fmap id Nothing = id Nothing

    -- Nothing = Nothing instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
  56. The Maybe Functor -- fmap id (Just a) = id

    (Just a) -- Just (id a) = Just a -- Just a = Just a instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
  57. The Maybe Functor -- fmap (p . q) = (fmap

    p) . (fmap q) instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
  58. The Maybe Functor -- fmap (p . q) Nothing =

    ((fmap p) . (fmap q)) Nothing -- Nothing = (fmap p) ((fmap q) Nothing) -- Nothing = (fmap p) Nothing -- Nothing = Nothing instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
  59. The Maybe Functor -- fmap (p . q) (Just a)

    = ((fmap p) . (fmap q)) (Just a) -- Just ((p . q) a) = (fmap p) ((fmap q) (Just a)) -- Just (p (q a)) = (fmap p) (Just (q a)) -- Just (p (q a)) = Just (p (q a)) instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)