Slide 1

Slide 1 text

This slide intentionally left blank

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Equational Reasoning Mihai Maruseac June 21, 2016

Slide 4

Slide 4 text

Equational reasoning is the method of manipulating structures such as formulas and expressions. The basic idea is that equals can be replaced by equals in any context.

Slide 5

Slide 5 text

Example f = sum . take 5 . repeat f 10 = ?

Slide 6

Slide 6 text

Example f = sum . take 5 . repeat f 10 = ? f 10 = sum . take 5 . repeat $ 10

Slide 7

Slide 7 text

Example f = sum . take 5 . repeat f 10 = ? f 10 = sum . take 5 . repeat $ 10 repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs

Slide 8

Slide 8 text

Example (beta reduction) repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (take 5 (repeat 10))

Slide 9

Slide 9 text

Example (beta reduction) repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (take 5 (repeat 10)) 5 > 0 so we take branch n > 0 of take

Slide 10

Slide 10 text

Example (beta reduction) repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (take 5 (repeat 10)) 5 > 0 so we take branch n > 0 of take Pattern match on (x:xs) so, expand repeat first

Slide 11

Slide 11 text

Example (beta reduction) repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (take 5 (repeat 10)) 5 > 0 so we take branch n > 0 of take Pattern match on (x:xs) so, expand repeat first

Slide 12

Slide 12 text

Example (beta reduction) repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (take 5 (repeat 10)) 5 > 0 so we take branch n > 0 of take Pattern match on (x:xs) so, expand repeat first f 10 = sum (take 5 (10 : repeat 10))

Slide 13

Slide 13 text

Example (beta reduction) repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (take 5 (repeat 10)) 5 > 0 so we take branch n > 0 of take Pattern match on (x:xs) so, expand repeat first f 10 = sum (take 5 (10 : repeat 10)) f 10 = sum (10 : take 4 (repeat 10))

Slide 14

Slide 14 text

Example repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (10 : take 4 (repeat 10))

Slide 15

Slide 15 text

Example repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (10 : take 4 (repeat 10)) Multiple possibilities to evaluate the expression

Slide 16

Slide 16 text

Example repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (10 : take 4 (repeat 10)) Multiple possibilities to evaluate the expression lazy vs eager evaluation

Slide 17

Slide 17 text

Diamond theorem Excluding ⊥, all evaluation paths lead to the same result. Diamond theorem, Church-Rosser exp1 exp2 exp1 arg fun exp2 fun arg res

Slide 18

Slide 18 text

Example repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (10 : take 4 (repeat 10))

Slide 19

Slide 19 text

Example repeat x = x : repeat x take n (x:xs) | n > 0 = x : take (n - 1) xs | otherwise = [] sum [] = 0 sum (x:xs) = x + sum xs f 10 = sum (10 : take 4 (repeat 10)) f 10 = sum (10 : take 4 (repeat 10)) f 10 = sum (10 : 10 : take 3 (repeat 10)) f 10 = sum (10 : 10 : 10 : take 2 (repeat 10)) f 10 = sum (10 : 10 : 10 : 10 : take 1 (repeat 10)) f 10 = sum (10 : 10 : 10 : 10 : 10 : take 0 (repeat 10)) f 10 = sum [10, 10, 10, 10, 10] f 10 = 50

Slide 20

Slide 20 text

Functional programming encourages equational reasoning

Slide 21

Slide 21 text

Functional programming encourages equational reasoning understanding evaluation / debugging typeclass rules GHC rewrite rules refactoring theorem proving optimizations algorithm design data structure design

Slide 22

Slide 22 text

Evaluation/Debugging evaluation: see previous example

Slide 23

Slide 23 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching

Slide 24

Slide 24 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching hard to do for big programs

Slide 25

Slide 25 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching hard to do for big programs lazy evaluation vs. stack-based debugging

Slide 26

Slide 26 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching hard to do for big programs lazy evaluation vs. stack-based debugging GHCi debugger

Slide 27

Slide 27 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching hard to do for big programs lazy evaluation vs. stack-based debugging GHCi debugger hard to use for large programs

Slide 28

Slide 28 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching hard to do for big programs lazy evaluation vs. stack-based debugging GHCi debugger hard to use for large programs Hood: Haskell Object Observation Debugger

Slide 29

Slide 29 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching hard to do for big programs lazy evaluation vs. stack-based debugging GHCi debugger hard to use for large programs Hood: Haskell Object Observation Debugger print intermediate data structure

Slide 30

Slide 30 text

Evaluation/Debugging evaluation: see previous example cool tool for teaching hard to do for big programs lazy evaluation vs. stack-based debugging GHCi debugger hard to use for large programs Hood: Haskell Object Observation Debugger print intermediate data structure use equational reasoning to reason about state around bug

Slide 31

Slide 31 text

Typeclass rules class Functor f where fmap :: (a -> b) -> f a -> f b

Slide 32

Slide 32 text

Typeclass rules class Functor f where fmap :: (a -> b) -> f a -> f b fmap id = id fmap (f . g) = fmap f . fmap g

Slide 33

Slide 33 text

Typeclass rules class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b

Slide 34

Slide 34 text

Typeclass rules class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b pure f <*> x = fmap f x pure id <*> v = v pure (.) <*> u <*> v <*> w = u <*> (v <*> w) pure f <*> pure x = pure (f x) u <*> pure y = pure ($ y) <*> u

Slide 35

Slide 35 text

Typeclass rules class Monoid m where mempty :: m mappend :: m -> m -> m mconcat :: [m] -> m mconcat = foldr mappend mempty (<>) = mappend

Slide 36

Slide 36 text

Typeclass rules class Monoid m where mempty :: m mappend :: m -> m -> m mconcat :: [m] -> m mconcat = foldr mappend mempty (<>) = mappend mempty <> x = x x <> mempty = x (x <> y) <> z = x <> (y <> z)

Slide 37

Slide 37 text

Typeclass rules these rules are not checked by compiler

Slide 38

Slide 38 text

Typeclass rules these rules are not checked by compiler prove them

Slide 39

Slide 39 text

Typeclass rules these rules are not checked by compiler prove them test with QuickCheck or similar

Slide 40

Slide 40 text

Typeclass rules these rules are not checked by compiler prove them test with QuickCheck or similar http://austinrochford.com/posts/ 2014-05-27-quickcheck-laws.html

Slide 41

Slide 41 text

Typeclass rules these rules are not checked by compiler prove them test with QuickCheck or similar http://austinrochford.com/posts/ 2014-05-27-quickcheck-laws.html parametricity makes some rules be always valid (Functor)

Slide 42

Slide 42 text

Typeclass rules these rules are not checked by compiler prove them test with QuickCheck or similar http://austinrochford.com/posts/ 2014-05-27-quickcheck-laws.html parametricity makes some rules be always valid (Functor) these rules hold over all instances of typeclass

Slide 43

Slide 43 text

Typeclass rules these rules are not checked by compiler prove them test with QuickCheck or similar http://austinrochford.com/posts/ 2014-05-27-quickcheck-laws.html parametricity makes some rules be always valid (Functor) these rules hold over all instances of typeclass same reasoning holds when moving from Maybe a to [a]

Slide 44

Slide 44 text

Typeclass rules these rules are not checked by compiler prove them test with QuickCheck or similar http://austinrochford.com/posts/ 2014-05-27-quickcheck-laws.html parametricity makes some rules be always valid (Functor) these rules hold over all instances of typeclass same reasoning holds when moving from Maybe a to [a] allow higher-level reasoning

Slide 45

Slide 45 text

Typeclass rules these rules are not checked by compiler prove them test with QuickCheck or similar http://austinrochford.com/posts/ 2014-05-27-quickcheck-laws.html parametricity makes some rules be always valid (Functor) these rules hold over all instances of typeclass same reasoning holds when moving from Maybe a to [a] allow higher-level reasoning easily change the semantics of the program with minimal impact on performance/accuracy/etc.

Slide 46

Slide 46 text

GHC rewrite rules {-# RULES "map/map" forall f g xs. map f (map g xs) = map (f.g) xs #-}

Slide 47

Slide 47 text

GHC rewrite rules {-# RULES "map/map" forall f g xs. map f (map g xs) = map (f.g) xs #-} map f . map g = map (f . g)

Slide 48

Slide 48 text

GHC rewrite rules {-# RULES "map/map" forall f g xs. map f (map g xs) = map (f.g) xs #-} map f . map g = map (f . g) List fusion function generating list function consuming list to generate result list = temporary data structure why not eliminate it?

Slide 49

Slide 49 text

List fusion :: Good producers List comprehensions Enumerations of simple types Explicit lists The (:) constructor

Slide 50

Slide 50 text

List fusion :: Good producers List comprehensions Enumerations of simple types Explicit lists The (:) constructor (++)

Slide 51

Slide 51 text

List fusion :: Good producers List comprehensions Enumerations of simple types Explicit lists The (:) constructor (++) map take, drop, filter iterate, repeat zip, zipWith

Slide 52

Slide 52 text

List fusion :: Good consumers List comprehensions array (++) foldr sum, product, all, any map take, drop, filter concat unzip zip, zipWith partition head sortBy

Slide 53

Slide 53 text

GHC rewrite rules (2) What if some equation is valid only for one type?

Slide 54

Slide 54 text

GHC rewrite rules (2) What if some equation is valid only for one type? or effective only for some types

Slide 55

Slide 55 text

GHC rewrite rules (2) What if some equation is valid only for one type? or effective only for some types specialize rules

Slide 56

Slide 56 text

GHC rewrite rules (2) What if some equation is valid only for one type? or effective only for some types specialize rules

Slide 57

Slide 57 text

GHC rewrite rules (2) What if some equation is valid only for one type? or effective only for some types specialize rules toDouble :: Real a => a -> Double toDouble = fromRational . toRational

Slide 58

Slide 58 text

GHC rewrite rules (2) What if some equation is valid only for one type? or effective only for some types specialize rules toDouble :: Real a => a -> Double toDouble = fromRational . toRational {-# RULES "toDouble/Int" toDouble = i2d #-} i2d (I# i) = D# (int2Double# i)

Slide 59

Slide 59 text

Refactoring HaRe: the Haskell Refactorer.

Slide 60

Slide 60 text

Theorem Proving Structural induction.

Slide 61

Slide 61 text

Theorem Proving Structural induction. data and codata

Slide 62

Slide 62 text

Theorem Proving Structural induction. data and codata final algebras and final coalgebras

Slide 63

Slide 63 text

Theorem Proving Structural induction. data and codata final algebras and final coalgebras

Slide 64

Slide 64 text

Theorem Proving Structural induction. data and codata final algebras and final coalgebras sum [] = 0 sum (a:as) = a + sum as

Slide 65

Slide 65 text

Theorem Proving Structural induction. data and codata final algebras and final coalgebras sum [] = 0 sum (a:as) = a + sum as sumSoFar x [] = [x] sumSoFar x (y:ys) = x : sumSoFar (x+y) ys

Slide 66

Slide 66 text

Data and (Structural) Induction sum [] = 0 sum (a:as) = a + sum as sum (map (+1) x) = length x + sum x

Slide 67

Slide 67 text

Data and (Structural) Induction sum [] = 0 sum (a:as) = a + sum as sum (map (+1) x) = length x + sum x Base case:

Slide 68

Slide 68 text

Data and (Structural) Induction sum [] = 0 sum (a:as) = a + sum as sum (map (+1) x) = length x + sum x Base case: [] sum (map (+1) []) = sum [] = 0 length [] + sum [] = 0 + 0 = 0

Slide 69

Slide 69 text

Data and (Structural) Induction sum [] = 0 sum (a:as) = a + sum as sum (map (+1) x) = length x + sum x Base case: [] sum (map (+1) []) = sum [] = 0 length [] + sum [] = 0 + 0 = 0 Inductive case:

Slide 70

Slide 70 text

Data and (Structural) Induction sum [] = 0 sum (a:as) = a + sum as sum (map (+1) x) = length x + sum x Base case: [] sum (map (+1) []) = sum [] = 0 length [] + sum [] = 0 + 0 = 0 Inductive case:(for all constructors) sum (map (+1) (x:xs)) = sum ((x+1) : map (+1) xs) = (x+1) + sum (map (+1) xs) = (x+1) + length xs + sum xs = (1 + length xs) + (x + sum xs) = length (x:xs) + sum (x:xs)

Slide 71

Slide 71 text

Codata and (Structural) Coinduction fib = 1 : 1 : zipWith (+) fib (tail fib) luc = 2 : 1 : zipWith (+) luc (tail luc)

Slide 72

Slide 72 text

Codata and (Structural) Coinduction fib = 1 : 1 : zipWith (+) fib (tail fib) luc = 2 : 1 : zipWith (+) luc (tail luc) 1, 1, 2, 3, 5, 8, 13, 21, 34 2, 1, 3, 4, 7, 11, 18, 29, 47

Slide 73

Slide 73 text

Codata and (Structural) Coinduction fib = 1 : 1 : zipWith (+) fib (tail fib) luc = 2 : 1 : zipWith (+) luc (tail luc) 1, 1, 2, 3, 5, 8, 13, 21, 34 2, 1, 3, 4, 7, 11, 18, 29, 47 Ln+2 = Fn+1 + 2 ∗ Fn

Slide 74

Slide 74 text

Codata and (Structural) Coinduction fib = 1 : 1 : zipWith (+) fib (tail fib) luc = 2 : 1 : zipWith (+) luc (tail luc) 1, 1, 2, 3, 5, 8, 13, 21, 34 2, 1, 3, 4, 7, 11, 18, 29, 47 Ln+2 = Fn+1 + 2 ∗ Fn luc !! (n+2) = fib !! (n+1) + 2 * fib !! n

Slide 75

Slide 75 text

Codata and (Structural) Coinduction fib = 1 : 1 : zipWith (+) fib (tail fib) luc = 2 : 1 : zipWith (+) luc (tail luc) 1, 1, 2, 3, 5, 8, 13, 21, 34 2, 1, 3, 4, 7, 11, 18, 29, 47 Ln+2 = Fn+1 + 2 ∗ Fn luc !! (n+2) = fib !! (n+1) + 2 * fib !! n tail (tail luc) = zipWith (+) (tail fib) (map (*2) fib)

Slide 76

Slide 76 text

Codata and (Structural) Coinduction fib = 1 : 1 : zipWith (+) fib (tail fib) luc = 2 : 1 : zipWith (+) luc (tail luc) tail (tail luc) = zipWith (+) (tail fib) (map (*2) fib) zipWith (+) (tail fib) (map (*2) fib) = zipWith (+) (1 : zipWith (+) fib (tail fib)) (2 : 2 : map (*2) (zipWith (+)fib (tail fib))) = 3 : zipWith (+) (zipWith (+) fib (tail fib)) (2 : map (*2) (zipWith (+) fib (tail fib))) = ...

Slide 77

Slide 77 text

More on codata Firstly, induction principles are well known and much used. The coinductive definition and proof principles for coalgebras are less well known by far, and often even not very clearly formulated. Rutten, 2000, seminal paper

Slide 78

Slide 78 text

More on codata Firstly, induction principles are well known and much used. The coinductive definition and proof principles for coalgebras are less well known by far, and often even not very clearly formulated. Rutten, 2000, seminal paper bisimilarity, bisimulation A property holds by induction if there is good reason for it to hold; whereas a property holds by coinduction if there is no good reason for it not to hold. Induction is about finite data, coinduction is about infinite codata.

Slide 79

Slide 79 text

Hermit Haskell Equational Reasoning Model-to-Implementation Tunnel http://ku-fpg.github.io/software/hermit/ https://hackage.haskell.org/package/hermit http://www.ittc.ku.edu/~afarmer/talks/unsw.html

Slide 80

Slide 80 text

Hermit Haskell Equational Reasoning Model-to-Implementation Tunnel http://ku-fpg.github.io/software/hermit/ https://hackage.haskell.org/package/hermit http://www.ittc.ku.edu/~afarmer/talks/unsw.html Similar: Coq, Idris

Slide 81

Slide 81 text

Hermit Haskell Equational Reasoning Model-to-Implementation Tunnel http://ku-fpg.github.io/software/hermit/ https://hackage.haskell.org/package/hermit http://www.ittc.ku.edu/~afarmer/talks/unsw.html Similar: Coq, Idris (dependent languages)

Slide 82

Slide 82 text

Hermit Haskell Equational Reasoning Model-to-Implementation Tunnel http://ku-fpg.github.io/software/hermit/ https://hackage.haskell.org/package/hermit http://www.ittc.ku.edu/~afarmer/talks/unsw.html Similar: Coq, Idris (dependent languages) Proving 4 color theorem

Slide 83

Slide 83 text

Optimizations

Slide 84

Slide 84 text

Solving sudoku

Slide 85

Slide 85 text

Solving sudoku type Matrix a = [Row a] type Row a = [a] type Grid = Matrix Digit type Digit = Char digits = [’1’..’9’] blank = (== ’0’) solve = filter valid . expand . choices

Slide 86

Slide 86 text

Solving sudoku type Matrix a = [Row a] type Row a = [a] type Grid = Matrix Digit type Digit = Char digits = [’1’..’9’] blank = (== ’0’) solve = filter valid . expand . choices 147 808 829 414 345 923 316 083 210 206 383 297 601

Slide 87

Slide 87 text

Solving sudoku solve = filter valid . expand . prune . choices

Slide 88

Slide 88 text

Solving sudoku solve = filter valid . expand . prune . choices 12 157 665 459 056 928 801

Slide 89

Slide 89 text

Solving sudoku solve = filter valid . expand . prune . choices 12 157 665 459 056 928 801 After some calculation solve = search . choices search m | not (safe m) = [] | complete m’ = [map (map (head) m’] | otherwise = concat (map search (expand1 m’)) where m’ = prune m

Slide 90

Slide 90 text

Solving sudoku solve = filter valid . expand . prune . choices 12 157 665 459 056 928 801 After some calculation solve = search . choices search m | not (safe m) = [] | complete m’ = [map (map (head) m’] | otherwise = concat (map search (expand1 m’)) where m’ = prune m Blazingly fast: 8s on all puzzles

Slide 91

Slide 91 text

In other languages lazy, functional languages: everything applies

Slide 92

Slide 92 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥

Slide 93

Slide 93 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible?

Slide 94

Slide 94 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible?

Slide 95

Slide 95 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA

Slide 96

Slide 96 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates

Slide 97

Slide 97 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours

Slide 98

Slide 98 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours running time: 500ms

Slide 99

Slide 99 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours running time: 500ms equational reasoning to translate to non-template version

Slide 100

Slide 100 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours running time: 500ms equational reasoning to translate to non-template version compile time: 10s

Slide 101

Slide 101 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours running time: 500ms equational reasoning to translate to non-template version compile time: 10s running time: 550ms

Slide 102

Slide 102 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours running time: 500ms equational reasoning to translate to non-template version compile time: 10s running time: 550ms

Slide 103

Slide 103 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours running time: 500ms equational reasoning to translate to non-template version compile time: 10s running time: 550ms lack of tooling → every calculation must be done by hand

Slide 104

Slide 104 text

In other languages lazy, functional languages: everything applies eager, functional languages: beware ⊥ non-functional languages: possible? C++ code for cypto code on CUDA C++ templates compilation: 24 hours running time: 500ms equational reasoning to translate to non-template version compile time: 10s running time: 550ms lack of tooling → every calculation must be done by hand IDE & automatic refactorings rarely help

Slide 105

Slide 105 text

Warning Beware of code that is too smart.

Slide 106

Slide 106 text

Warning Beware of code that is too smart. https://mail.haskell.org/pipermail/haskell-cafe/ 2009-March/058475.html

Slide 107

Slide 107 text

Warning Beware of code that is too smart. https://mail.haskell.org/pipermail/haskell-cafe/ 2009-March/058475.html different versions of same code different coding styles and levels of Haskell knowledge timings between versions derivation of efficient solution

Slide 108

Slide 108 text

Warning Beware of code that is too smart. https://mail.haskell.org/pipermail/haskell-cafe/ 2009-March/058475.html different versions of same code different coding styles and levels of Haskell knowledge timings between versions derivation of efficient solution and a not-so-trivial bug

Slide 109

Slide 109 text

Clever Perl code is what you hope you understood in the past, when you wrote it; clever Haskell code is what you hope you’ll understand in the future, when you’ll write it yourself! Sjur Gjøstein Karevoll, paraphrased