Slide 1

Slide 1 text

Functional Programming for Dummies* *) people without a degree in Computer Science

Slide 2

Slide 2 text

Functional Programming is...

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Referential Transparency

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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.

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

Recursion To understand recursion, you must first understand recursion.

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

Recursion average($xs)

Slide 28

Slide 28 text

Recursion average($xs)

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

Recursion 6 / 3

Slide 48

Slide 48 text

Recursion 6 / 3

Slide 49

Slide 49 text

Recursion 2

Slide 50

Slide 50 text

Recursion 2

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

Recursion

Slide 55

Slide 55 text

Pointfree Programming

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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;

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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.

Slide 77

Slide 77 text

Algebraic Data Types

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

6. Hindley-Milner Type System

Slide 86

Slide 86 text

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.

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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’

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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’

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

Category Theory

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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)

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

0. Category Theory

Slide 103

Slide 103 text

Category Theory for Programmers Bartosz Milewski

Slide 104

Slide 104 text

Category Theory

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

Functors

Slide 108

Slide 108 text

Functors

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

Functor Laws

Slide 111

Slide 111 text

Functor Laws

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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)

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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)

Slide 117

Slide 117 text

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)

Slide 118

Slide 118 text

Category Theory

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

Thnx @scataco