250

# Functional Programming for "Dummies"

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

July 05, 2017

## Transcript

1. ### Functional Programming for Dummies* *) people without a degree in

Computer Science

Framework

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.

\$i; }
9. ### Referential Transparency function main() { \$i = 41; \$i++; //

<- evaluates to 41 return \$i; }

\$i; }
11. ### Referential Transparency function main() { \$i = 41; \$j =

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

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

42; return \$j; }
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.

Recursion

/ 2; }
17. ### Immutability function average(\$a, \$b) { \$total = 0; \$total +=

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

return \$total / 2; }
19. ### Immutable Data Structures \$x = 1; \$y = 2; \$p

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

// <- 1 tail(\$xs) // <- [2, [3, null]] \$empty = null;

23. ### Recursion function length(\$xs) { \$length = 0; foreach (\$xs as

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

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

0; } return 1 + length(tail(\$xs)); }
26. ### Recursion function sum(\$xs) { if (\$xs === null) { return

0; } return head(\$xs) + sum(tail(\$xs)); }

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

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

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

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

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

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

[2, [3, null]]])))

[3, null]]))

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

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

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

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

+ 1 + 1 + length(null))

+ 1 + 1 + 0)

+ 1 + 1 + 0)

51. ### Recursion function sum(\$xs) { if (\$xs === null) { return

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

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

return \$start; } return sum(tail(\$xs), head(\$xs) + \$start); // <- tail recursion }

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

Functional Composition
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.
58. ### Higher Order Functions function sum(xs) { if (xs === null)

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

null ? 0 : head(xs) + sum(tail(xs));

+ y;
61. ### Higher Order Functions const add = x => y =>

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

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

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

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

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

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

xs => xs === null ? z : f(head(xs))(foldr(f)(z)(tail(xs)))
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)));
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)));
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)));
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)));
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);
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;
74. ### Higher Order Functions const ones = map(constant(1)); const length =

compose(sum)(ones);
75. ### Pointfree Programming const sum = foldr(add)(0); const ones = map(constant(1));

const length = compose(sum)(ones); // not one single parameter
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.

78. ### Algebraic Data Types Just like there are rules for manipulating

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

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

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

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

isNothing :: Maybe a -> Bool isNothing (Just a) = False isNothing Nothing = True
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
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

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

96. ### Monads Once you understand monads for yourself, you lose the

ability to explain them to others. – Douglas Crockford

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)
100. ### The Maybe Functor isEven x = x `mod` == 0

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

maybeEven = fmap isEven maybeEven (Just 1) -- Just False maybeEven Nothing -- Nothing

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

another.

109. ### Functor Laws category theory demands the following: fmap id =

id fmap (p . q) = (fmap p) . (fmap q)

112. ### The Maybe Functor -- fmap id = id instance Functor

Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
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)
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)
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)
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)
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)