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. Functional Programming
    for Dummies*
    *) people without a degree in Computer Science

    View Slide

  2. Functional
    Programming
    is...

    View Slide

  3. “Functional” Programming
    function set_id($record, $id)
    {
    $record['id'] = $id;
    }

    View Slide

  4. 1. Properties of the Language
    2. Common Practices
    3. Theoretical Framework

    View Slide

  5. 1. Referential Transparency
    2. Pointfree Programming
    3. Algebraic Data Types

    View Slide

  6. Referential
    Transparency

    View Slide

  7. Referential Transparency
    An expression is referentially transparent if you can
    replace that expression with its corresponding value without
    changing the behavior of the program.

    View Slide

  8. Referential Transparency
    function main()
    {
    $i = 41;
    $i++;
    return $i;
    }

    View Slide

  9. Referential Transparency
    function main()
    {
    $i = 41;
    $i++; // <- evaluates to 41
    return $i;
    }

    View Slide

  10. Referential Transparency
    function main()
    {
    $i = 41;
    41;
    return $i;
    }

    View Slide

  11. Referential Transparency
    function main()
    {
    $i = 41;
    $j = $i + 1;
    return $j;
    }

    View Slide

  12. Referential Transparency
    function main()
    {
    $i = 41;
    $j = $i + 1; // <- evaluates to 42
    return $j;
    }

    View Slide

  13. Referential Transparency
    function main()
    {
    $i = 41;
    $j = 42;
    return $j;
    }

    View Slide

  14. 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.

    View Slide

  15. 1. Pure Functions
    2. Immutability
    3. Immutable Data Structures
    4. Recursion

    View Slide

  16. Pure Functions
    function average($a, $b)
    {
    return ($a + $b) / 2;
    }

    View Slide

  17. Immutability
    function average($a, $b)
    {
    $total = 0;
    $total += $a; // <- fail!
    $total += $b; // <- fail!
    return $total / 2;
    }

    View Slide

  18. Immutability
    function average($a, $b)
    {
    $total = $a + $b;
    return $total / 2;
    }

    View Slide

  19. Immutable Data Structures
    $x = 1;
    $y = 2;
    $p = [0, 2];
    $p[2] = 5; // <- fail

    View Slide

  20. Immutable Data Structures
    $xs = [1, [2, [3, null]]];
    head($xs) // <- 1
    tail($xs) // <- [2, [3, null]]
    $empty = null;

    View Slide

  21. Recursion
    To understand recursion, you must first understand
    recursion.

    View Slide

  22. Recursion
    function average($xs)
    {
    return sum($xs) / length($xs);
    }

    View Slide

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

    View Slide

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

    View Slide

  25. Recursion
    function length($xs)
    {
    if ($xs === null) {
    return 0;
    }
    return 1 + length(tail($xs));
    }

    View Slide

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

    View Slide

  27. Recursion
    average($xs)

    View Slide

  28. Recursion
    average($xs)

    View Slide

  29. Recursion
    average([1, [2, [3, null]]])

    View Slide

  30. Recursion
    average([1, [2, [3, null]]])

    View Slide

  31. Recursion
    sum([1, [2, [3, null]]]) / length([1, [2, [3, null]]])

    View Slide

  32. Recursion
    sum([1, [2, [3, null]]]) / length([1, [2, [3, null]]])

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  45. Recursion
    (1 + 2 + 3 + 0) / (1 + 1 + 1 + 0)

    View Slide

  46. Recursion
    (1 + 2 + 3 + 0) / (1 + 1 + 1 + 0)

    View Slide

  47. Recursion
    6 / 3

    View Slide

  48. Recursion
    6 / 3

    View Slide

  49. Recursion
    2

    View Slide

  50. Recursion
    2

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  54. Recursion

    View Slide

  55. Pointfree
    Programming

    View Slide

  56. 1. Currying
    2. Partial Application
    3. Higher Order Functions
    4. Functional Composition

    View Slide

  57. Higher Order Functions
    A higher order function is a function that accepts a
    function as one of its parameters and/or returns a function.

    View Slide

  58. Higher Order Functions
    function sum(xs) {
    if (xs === null) {
    return 0;
    }
    return head(xs) + sum(tail(xs));
    }

    View Slide

  59. Higher Order Functions
    const sum = xs =>
    xs === null ? 0 : head(xs) + sum(tail(xs));

    View Slide

  60. Higher Order Functions
    const add = (x, y) =>
    x + y;

    View Slide

  61. Higher Order Functions
    const add = x => y => // <- currying
    x + y;

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  68. 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)));

    View Slide

  69. 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)));

    View Slide

  70. 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)));

    View Slide

  71. 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)));

    View Slide

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

    View Slide

  73. 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;

    View Slide

  74. Higher Order Functions
    const ones = map(constant(1));
    const length = compose(sum)(ones);

    View Slide

  75. Pointfree Programming
    const sum = foldr(add)(0);
    const ones = map(constant(1));
    const length = compose(sum)(ones);
    // not one single parameter

    View Slide

  76. 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.

    View Slide

  77. Algebraic
    Data Types

    View Slide

  78. Algebraic Data Types
    Just like there are rules for manipulating numbers, there
    are rules for manipulating types.

    View Slide

  79. 1. Sum Types
    2. Product Types
    3. Type Constructors
    4. Recursive Type Definitions
    5. Pattern Matching

    View Slide

  80. Sum Types
    data Bool = True | False
    not :: Bool -> Bool
    not True = False
    not False = True

    View Slide

  81. Product Types
    data Point = Point Int Int
    translate :: Point -> Point -> Point
    translate (Point dx dy) (Point x y) =
    Point (x + dx) (y + dy)

    View Slide

  82. Type Constructors
    data Maybe a = Nothing | Just a
    isNothing :: Maybe a -> Bool
    isNothing (Just a) = False
    isNothing Nothing = True

    View Slide

  83. 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

    View Slide

  84. Pattern Matching
    translate (Point dx dy) (Point x y) =
    Point (x + dx) (y + dy)
    length Nil = 0
    length (Cons x xs) = 1 + length xs

    View Slide

  85. 6. Hindley-Milner Type System

    View Slide

  86. 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.

    View Slide

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

    View Slide

  88. 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’

    View Slide

  89. 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]’

    View Slide

  90. 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’

    View Slide

  91. 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

    View Slide

  92. 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

    View Slide

  93. 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

    View Slide

  94. Hindley-Milner Type System
    (->) is a Type Constructor

    View Slide

  95. Category
    Theory

    View Slide

  96. Monads
    Once you understand monads for yourself, you lose the
    ability to explain them to others. – Douglas Crockford

    View Slide

  97. 1. Functors
    2. Monoid
    3. Applicatives
    4. Monads

    View Slide

  98. 1. Functors
    2. Monoid
    3. Applicatives
    4. Monads

    View Slide

  99. 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)

    View Slide

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

    View Slide

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

    View Slide

  102. 0. Category Theory

    View Slide

  103. Category Theory for Programmers
    Bartosz Milewski

    View Slide

  104. Category Theory

    View Slide

  105. 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

    View Slide

  106. Functors
    A functor is a mapping from one category to another.

    View Slide

  107. Functors

    View Slide

  108. Functors

    View Slide

  109. Functor Laws
    category theory demands the following:
    fmap id = id
    fmap (p . q) = (fmap p) . (fmap q)

    View Slide

  110. Functor Laws

    View Slide

  111. Functor Laws

    View Slide

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

    View Slide

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

    View Slide

  114. 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)

    View Slide

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

    View Slide

  116. 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)

    View Slide

  117. 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)

    View Slide

  118. Category Theory

    View Slide

  119. 1. Referential Transparency
    2. Pointfree Programming
    3. Algebraic Data Types

    View Slide

  120. Thnx
    @scataco

    View Slide