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

Equational Reasoning in Programming

Equational Reasoning in Programming

Bucharest FP

June 21, 2016
Tweet

More Decks by Bucharest FP

Other Decks in Programming

Transcript

  1. This slide intentionally left blank

    View full-size slide

  2. Equational Reasoning
    Mihai Maruseac
    June 21, 2016

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  19. Functional programming encourages equational reasoning

    View full-size slide

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

    View full-size slide

  21. Evaluation/Debugging
    evaluation: see previous example

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  36. Typeclass rules
    these rules are not checked by compiler

    View full-size slide

  37. Typeclass rules
    these rules are not checked by compiler
    prove them

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  47. 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?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  58. Refactoring
    HaRe: the Haskell Refactorer.

    View full-size slide

  59. Theorem Proving
    Structural induction.

    View full-size slide

  60. Theorem Proving
    Structural induction.
    data and codata

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  68. 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:

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  75. 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)))
    = ...

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  82. Optimizations

    View full-size slide

  83. Solving sudoku

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  90. In other languages
    lazy, functional languages: everything applies

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  104. Warning
    Beware of code that is too smart.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide