Lecture 14. Foldables and traversables Functional Programming - - PowerPoint PPT Presentation

lecture 14 foldables and traversables
SMART_READER_LITE
LIVE PREVIEW

Lecture 14. Foldables and traversables Functional Programming - - PowerPoint PPT Presentation

Lecture 14. Foldables and traversables Functional Programming 2019/20 Matthijs Vkr [ Faculty of Science Information and Computing Sciences] 0 Goals How do we calculate summaries of data structures other than lists? Learn about


slide-1
SLIDE 1

[Faculty of Science Information and Computing Sciences]

Lecture 14. Foldables and traversables

Functional Programming 2019/20

Matthijs Vákár

slide-2
SLIDE 2

[Faculty of Science Information and Computing Sciences] 1

Goals

▶ How do we calculate summaries of data structures

  • ther than lists?

▶ Learn about Monoid and Foldable type classes

▶ How do we map impure functions over data structures?

▶ Learn about Applicative and Traversable type classes

▶ See some examples of monadic and applicative code in action. Chapter 14 from Hutton’s book

slide-3
SLIDE 3

[Faculty of Science Information and Computing Sciences] 2

Our three example data types for today

Binary trees: data Tree a = Leaf | Node (Tree a) a (Tree a) Rose trees: data Rose a = RLeaf | RNode a [Rose a] ASTs: data Expr x = Var x | Val Int | Add (Expr x) (Expr x)

slide-4
SLIDE 4

[Faculty of Science Information and Computing Sciences] 3

Linear summaries: Monoids and Foldables

slide-5
SLIDE 5

[Faculty of Science Information and Computing Sciences] 4

Summaries to calculate

▶ Sums, products of entries ▶ And/or of entries ▶ Used variables ▶ Composition of all functions in data structure ▶ Parity of Booleans in data structure Monoids and folds abstract the idea of combining elements in a well-behaved way!

slide-6
SLIDE 6

[Faculty of Science Information and Computing Sciences] 5

Monoids

Some types have an intrinsic notion of combination ▶ We already hinted at it when describing folds ▶ Monoids provide an associative binary operation with an identity element class Monoid m where mempty :: m mappend :: m -> m -> m mconcat :: [m] -> m mconcat = foldr mappend mempty

slide-7
SLIDE 7

[Faculty of Science Information and Computing Sciences] 6

Monoids: example

Lists [T] are monoids regardless of their contained type T instance Monoid [t] where mempty = []

  • - empty list

mappend = (++)

  • - concatenation

mconcat = concat The simplest monoids in a sense (jargon: free monoids)

slide-8
SLIDE 8

[Faculty of Science Information and Computing Sciences] 7

Monoid laws

Monoids capture well-behaved notion of combination, respecting these laws: mempty <> y = y

  • - left identity

x <> mempty = x

  • - right identity

(x <> y) <> z = x <> (y <> z) -- associativity We write mappend infjx as <>. Do these remind of you anything?

slide-9
SLIDE 9

[Faculty of Science Information and Computing Sciences] 8

Some examples of monoids

Can you come up with some examples of monoids?

slide-10
SLIDE 10

[Faculty of Science Information and Computing Sciences] 9

Folds and Monoids

Recall, folding on lists: foldr :: (a -> b -> b) -> b -> [a] -> b foldl :: (b -> a -> b) -> b -> [a] -> b We have seen, because of associativity and identity laws: foldr mappend mempty = foldl mappend mempty for any monoid! Note that monoids may be non-commmutative, so that foldr mappend mempty /= foldr (flip mappend) mempty

slide-11
SLIDE 11

[Faculty of Science Information and Computing Sciences] 9

Folds and Monoids

Recall, folding on lists: foldr :: (a -> b -> b) -> b -> [a] -> b foldl :: (b -> a -> b) -> b -> [a] -> b We have seen, because of associativity and identity laws: foldr mappend mempty = foldl mappend mempty for any monoid! Note that monoids may be non-commmutative, so that foldr mappend mempty /= foldr (flip mappend) mempty

slide-12
SLIDE 12

[Faculty of Science Information and Computing Sciences] 10

Generalizing foldr?

foldr :: (a -> b -> b) -> b -> [a] -> b (a -> b -> b) -> [a] -> b -> b (a -> End b ) -> [a] -> End b foldMap :: Monoid m => (a -> m) -> [a] -> m Does this buy us anything?

slide-13
SLIDE 13

[Faculty of Science Information and Computing Sciences] 11

Foldables

Want: foldr :: (a -> b -> b) -> b -> t a -> b

  • r

foldMap :: Monoid m => (a -> m) -> t a -> m for some other container type t. t had better be a functor…

slide-14
SLIDE 14

[Faculty of Science Information and Computing Sciences] 12

Foldables

Data structure we can fold over, like lists: class Functor t => Foldable t where foldr :: (a -> b -> b) -> b -> t a -> b foldr op i = ??? foldMap :: Monoid m => (a -> m) -> t a -> m foldMap f = ??? toList :: t a -> [a] toList = ??? fold :: Monoid m => t m -> m fold = ???

slide-15
SLIDE 15

[Faculty of Science Information and Computing Sciences] 13

Foldables

Data structure we can fold over, like lists: class Functor t => Foldable t where foldr :: (a -> b -> b) -> b -> t a -> b foldr op i = foldr op i . toList foldMap :: Monoid m => (a -> m) -> t a -> m foldMap f = mconcat . map f . toList toList :: t a -> [a] toList = foldr (:) [] fold :: Monoid m => t m -> m fold = foldMap id In essence, a data type that we can linearize to a list…

slide-16
SLIDE 16

[Faculty of Science Information and Computing Sciences] 14

Some examples

Let’s implement Foldable for Tree, Rose and Expr! See how they solve our initial problem!

slide-17
SLIDE 17

[Faculty of Science Information and Computing Sciences] 15

Mapping Impure Functions: Applicatives and Traversables

slide-18
SLIDE 18

[Faculty of Science Information and Computing Sciences] 16

Mapping impure functions

▶ A stateful walk of a tree ▶ A walking a rose tree while performing IO ▶ Trying to evaluate an expression while accumulating errors ▶ Idea: keep shape of data structure; replace entries using impure function; accumulate side efgects on the outside Applicatives and traversals abstract the idea of mapping impure functions in a well-behaved way!

slide-19
SLIDE 19

[Faculty of Science Information and Computing Sciences] 17

The functor - applicative - monad hierarchy

class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b class Applicative f => Monad f where return :: a -> f a -- equals Applicative's pure (>>=) :: f a -> (a -> f b) -> f b

slide-20
SLIDE 20

[Faculty of Science Information and Computing Sciences] 18

Recall: Applicatives from Monads

Every monad induces an applicative pure = return af <*> ax = do f <- af x <- ax return (f x) But not every applicative arises that way!

slide-21
SLIDE 21

[Faculty of Science Information and Computing Sciences] 19

Example: Error Accumulation

Example of Applicative that does not come from Monad data Error m a = Error m | OK a How is Error m a functor? An applicative? instance Monoid m => Applicative (Error m) where pure = OK (Error m1) <*> (Error m2) = Error (m1 <> m2) (Error m1) <*> (OK a) = Error m1 (OK f) <*> (Error m2) = Error m2 (OK f) <*> (OK a) = OK (f a) Why not from a monad?

slide-22
SLIDE 22

[Faculty of Science Information and Computing Sciences] 19

Example: Error Accumulation

Example of Applicative that does not come from Monad data Error m a = Error m | OK a How is Error m a functor? An applicative? instance Monoid m => Applicative (Error m) where pure = OK (Error m1) <*> (Error m2) = Error (m1 <> m2) (Error m1) <*> (OK a) = Error m1 (OK f) <*> (Error m2) = Error m2 (OK f) <*> (OK a) = OK (f a) Why not from a monad?

slide-23
SLIDE 23

[Faculty of Science Information and Computing Sciences] 20

Traversables

Data structure we can traverse/walk: class Foldable t => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) traverse g ta = ??? sequenceA :: Applicative f => t (f a) -> f (t a) sequenceA = ??? Think of traverse as a map over t using an impure function :: a -> f b

slide-24
SLIDE 24

[Faculty of Science Information and Computing Sciences] 21

Traversables

Data structure we can traverse/walk: class Foldable t => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) traverse g ta = sequenceA (fmap g ta) sequenceA :: Applicative f => t (f a) -> f (t a) sequenceA = traverse id Think of traverse as a map over t using an impure function :: a -> f b

slide-25
SLIDE 25

[Faculty of Science Information and Computing Sciences] 22

Some examples

Let’s implement Foldable for Tree, Rose and Expr!

slide-26
SLIDE 26

[Faculty of Science Information and Computing Sciences] 23

Traversing with the Identity Applicative

We have the identity monad newtype Identity' a = Identity' {runIdentity' :: a} instance Monad Identity' where return x = Identity' x x >>= f = f (runIdentity' x) Traversals are impure maps: fmap :: Traversable t => (a -> b) -> t a -> t b fmap == runIdentity . traverse (Identity . f)

slide-27
SLIDE 27

[Faculty of Science Information and Computing Sciences] 23

Traversing with the Identity Applicative

We have the identity monad newtype Identity' a = Identity' {runIdentity' :: a} instance Monad Identity' where return x = Identity' x x >>= f = f (runIdentity' x) Traversals are impure maps: fmap :: Traversable t => (a -> b) -> t a -> t b fmap == runIdentity . traverse (Identity . f)

slide-28
SLIDE 28

[Faculty of Science Information and Computing Sciences] 24

Relating Monoids and Applicatives, Folds and Traversals

slide-29
SLIDE 29

[Faculty of Science Information and Computing Sciences] 25

Phantom Types: All Monoids Are Applicatives

Introduce fake type dependency: newtype Const a b = Const { getConst :: a } instance Monoid m => Applicative (Const m) where pure _ = Const mempty (<*>) (Const f) (Const b) = Const (f <> b) Claim: traversing with Const is the same as folding: foldMap :: (Traversable t, Monoid m) => (a -> m) -> t a -> m foldMap f = getConst . sequenceA . fmap (Const . f)

slide-30
SLIDE 30

[Faculty of Science Information and Computing Sciences] 25

Phantom Types: All Monoids Are Applicatives

Introduce fake type dependency: newtype Const a b = Const { getConst :: a } instance Monoid m => Applicative (Const m) where pure _ = Const mempty (<*>) (Const f) (Const b) = Const (f <> b) Claim: traversing with Const is the same as folding: foldMap :: (Traversable t, Monoid m) => (a -> m) -> t a -> m foldMap f = getConst . sequenceA . fmap (Const . f)

slide-31
SLIDE 31

[Faculty of Science Information and Computing Sciences] 26

Foldables and Traversables in practice

▶ We can derive Foldable and Traversable instances (using a compiler extension)! ▶ The built-in instances for tuples can be very confusing ▶ A little game Prelude> minimum(1,100) Prelude> let splat = splitAt 5 [0..10] Prelude> splat ([0,1,2,3,4],[5,6,7,8,9,10]) Prelude> concat splat

slide-32
SLIDE 32

[Faculty of Science Information and Computing Sciences] 27

Foldables and Traversables in practice

▶ We can derive Foldable and Traversable instances (using a compiler extension)! ▶ The built-in instances for tuples can be very confusing ▶ A little game Prelude> minimum(1,100) 100 Prelude> let splat = splitAt 5 [0..10] Prelude> splat ([0,1,2,3,4],[5,6,7,8,9,10]) Prelude> concat splat [5,6,7,8,9,10]

slide-33
SLIDE 33

[Faculty of Science Information and Computing Sciences] 28

Prelude> fmap (+1) [1,2] [2,3] Prelude> fmap (+1) (1,2) Prelude> let xs = [(1,"hello"),(2,"world")] Prelude> length "world" 5 Prelude> length (lookup 2 xs) Prelude> let y = lookup 100 xs Prelude> null y True Prelude> length y

slide-34
SLIDE 34

[Faculty of Science Information and Computing Sciences] 29

Prelude> fmap (+1) [1,2] [2,3] Prelude> fmap (+1) (1,2) (1,3) Prelude> let xs = [(1,"hello"),(2,"world")] Prelude> length "world" 5 Prelude> length (lookup 2 xs) 1 Prelude> let y = lookup 100 xs Prelude> null y True Prelude> length y

slide-35
SLIDE 35

[Faculty of Science Information and Computing Sciences] 30

Summary

▶ Monoids capture a notion of summary/combination of values ▶ Foldables are data types that can be cast to a list ▶ They let us calculate summaries of the values in a data type Applicatives capture a notion of side efgect Traversables are data types that we can map efgectful functions over Monoids/foldables are a special case of applicatives/traversables (by using Phantom types)

slide-36
SLIDE 36

[Faculty of Science Information and Computing Sciences] 30

Summary

▶ Monoids capture a notion of summary/combination of values ▶ Foldables are data types that can be cast to a list ▶ They let us calculate summaries of the values in a data type ▶ Applicatives capture a notion of side efgect ▶ Traversables are data types that we can map efgectful functions over ▶ Monoids/foldables are a special case of applicatives/traversables (by using Phantom types)

slide-37
SLIDE 37

[Faculty of Science Information and Computing Sciences] 31

Where to from here?

Talen en compilers! ▶ Effjcient parsing using applicatives ▶ Lots of traversals ▶ Recursion schemes: much more interesting generalization of folds to other data types ▶ Plenty of other cool FP tricks