Interleaving Data and Effects Patricia Johann Appalachian State - - PowerPoint PPT Presentation

interleaving data and effects
SMART_READER_LITE
LIVE PREVIEW

Interleaving Data and Effects Patricia Johann Appalachian State - - PowerPoint PPT Presentation

Interleaving Data and Effects Patricia Johann Appalachian State University cs.appstate.edu/ johannp Joint work with Bob Atkey, Neil Ghani, and Bart Jacobs Haskell Symposium 2014 Programs, Data, and Effects Programming languages provide


slide-1
SLIDE 1

Interleaving Data and Effects

Patricia Johann Appalachian State University

cs.appstate.edu/

∼johannp

Joint work with Bob Atkey, Neil Ghani, and Bart Jacobs

Haskell Symposium 2014

slide-2
SLIDE 2

Programs, Data, and Effects

  • Programming languages provide a wide array of constructs for storing

and manipulating data – built-in data types (Bool, Int, Float,...) – lists – trees – arrays

slide-3
SLIDE 3

Programs, Data, and Effects

  • Programming languages provide a wide array of constructs for storing

and manipulating data – built-in data types (Bool, Int, Float,...) – lists – trees – arrays

  • Often these data types are pure, i.e., do not incorporate effects
slide-4
SLIDE 4

Programs, Data, and Effects

  • Programming languages provide a wide array of constructs for storing

and manipulating data – built-in data types (Bool, Int, Float,...) – lists – trees – arrays

  • Often these data types are pure, i.e., do not incorporate effects
  • However, sometimes data types not only to incorporate effects, but

also to interleave them with pure data

slide-5
SLIDE 5

Programs, Data, and Effects

  • Programming languages provide a wide array of constructs for storing

and manipulating data – built-in data types (Bool, Int, Float,...) – lists – trees – arrays

  • Often these data types are pure, i.e., do not incorporate effects
  • However, sometimes data types not only to incorporate effects, but

also to interleave them with pure data

  • Unfortunately, this is not always reflected in the types themselves
slide-6
SLIDE 6

Scenario I: (Implicitly) Interleaved Non-termination

  • Effects are implicitly built into every Haskell type: every Haskell type

allows the possiblity of non-termination while inspecting a pure value

  • f that type
slide-7
SLIDE 7

Scenario I: (Implicitly) Interleaved Non-termination

  • Effects are implicitly built into every Haskell type: every Haskell type

allows the possiblity of non-termination while inspecting a pure value

  • f that type
  • So not only is non-termination present in a type like [a], but because

non-termination is possible at every Haskell type — including the element type a — it’s actually interleaved throughout the entire type!

slide-8
SLIDE 8

Scenario I: (Implicitly) Interleaved Non-termination

  • Effects are implicitly built into every Haskell type: every Haskell type

allows the possiblity of non-termination while inspecting a pure value

  • f that type
  • So not only is non-termination present in a type like [a], but because

non-termination is possible at every Haskell type — including the element type a — it’s actually interleaved throughout the entire type!

  • In particular, because of Haskell’s lazy semantics, Haskell data struc-

tures can be infinite, as well as finite. – [a] is the type of finite and infinite lists of elements of type a.

slide-9
SLIDE 9

Scenario I: (Implicitly) Interleaved Non-termination

  • Effects are implicitly built into every Haskell type: every Haskell type

allows the possiblity of non-termination while inspecting a pure value

  • f that type
  • So not only is non-termination present in a type like [a], but because

non-termination is possible at every Haskell type — including the element type a — it’s actually interleaved throughout the entire type!

  • In particular, because of Haskell’s lazy semantics, Haskell data struc-

tures can be infinite, as well as finite. – [a] is the type of finite and infinite lists of elements of type a.

  • But neither the presence of non-termination effects, nor their inter-

leaving, is evident from the types themselves.

slide-10
SLIDE 10

Scenario II: (Implicitly) Interleaved IO Effects

  • The type of the Haskell library function

hGetContents :: Handle → IO [Char] suggests that it reads all the available data from the file referenced by Handle as an IO action and yields the list of characters as pure data

slide-11
SLIDE 11

Scenario II: (Implicitly) Interleaved IO Effects

  • The type of the Haskell library function

hGetContents :: Handle → IO [Char] suggests that it reads all the available data from the file referenced by Handle as an IO action and yields the list of characters as pure data

  • The standard implementation does not read data from the handle until

the list is accessed by the program, so the effect of reading from the file handle is implicitly interleaved with computation on the (pure) list

slide-12
SLIDE 12

Scenario II: (Implicitly) Interleaved IO Effects

  • The type of the Haskell library function

hGetContents :: Handle → IO [Char] suggests that it reads all the available data from the file referenced by Handle as an IO action and yields the list of characters as pure data

  • The standard implementation does not read data from the handle until

the list is accessed by the program, so the effect of reading from the file handle is implicitly interleaved with computation on the (pure) list

  • This interleaving is not reflected in the type of hGetContents, so

– IO errors that occur during reading are reported by throwing excep- tions from pure code — possibly long after the call to hGetContents – The handle is implicitly closed when the end of the file is reached, but if the end of file is never reached the handle will never be closed – Since the programmer cannot always predict when reads will occur, it is not safe for them to close the file handle

slide-13
SLIDE 13

Question I: How can we make the interleaving

  • f data and effects explicit in

types?

slide-14
SLIDE 14

Inductive Data Types with Effects

  • The type of lists interleaved with possible non-termination can be given

as data List′lazy a newtype Listlazy a = = Nillazy | Conslazy a (Listlazy a) Listlazy (List′

lazy a)⊥

slide-15
SLIDE 15

Inductive Data Types with Effects

  • The type of lists interleaved with possible non-termination can be given

as data List′lazy a newtype Listlazy a = = Nillazy | Conslazy a (Listlazy a) Listlazy (List′

lazy a)⊥

  • The type of lists interleaved with IO operations can be given as

data List′

io

newtype Listio = = Nilio | Consio Char Listio Listio (IO List′

io)

slide-16
SLIDE 16

Question II: How can we program effectively with, and reason effectively about, such “effectful” data types?

slide-17
SLIDE 17

Structure of This Talk

  • Recall: Standard initial algebra techniques
slide-18
SLIDE 18

Structure of This Talk

  • Recall: Standard initial algebra techniques
  • Argue: Straightforward application of initial algebra techniques is at

the wrong level of abstraction for effectful data types

slide-19
SLIDE 19

Structure of This Talk

  • Recall: Standard initial algebra techniques
  • Argue: Straightforward application of initial algebra techniques is at

the wrong level of abstraction for effectful data types

  • Instead: Separate pure and effectful parts using f-and-m-algebras
slide-20
SLIDE 20

Structure of This Talk

  • Recall: Standard initial algebra techniques
  • Argue: Straightforward application of initial algebra techniques is at

the wrong level of abstraction for effectful data types

  • Instead: Separate pure and effectful parts using f-and-m-algebras

– f-algebras for a functor f describe the pure parts of an effectful data type

slide-21
SLIDE 21

Structure of This Talk

  • Recall: Standard initial algebra techniques
  • Argue: Straightforward application of initial algebra techniques is at

the wrong level of abstraction for effectful data types

  • Instead: Separate pure and effectful parts using f-and-m-algebras

– f-algebras for a functor f describe the pure parts of an effectful data type – m-Eilenberg-Moore algebras for a monad m describe the effects

slide-22
SLIDE 22

Structure of This Talk

  • Recall: Standard initial algebra techniques
  • Argue: Straightforward application of initial algebra techniques is at

the wrong level of abstraction for effectful data types

  • Instead: Separate pure and effectful parts using f-and-m-algebras

– f-algebras for a functor f describe the pure parts of an effectful data type – m-Eilenberg-Moore algebras for a monad m describe the effects

  • Represent: Effectful data types as initial f-and-m-algebras
slide-23
SLIDE 23

Structure of This Talk

  • Recall: Standard initial algebra techniques
  • Argue: Straightforward application of initial algebra techniques is at

the wrong level of abstraction for effectful data types

  • Instead: Separate pure and effectful parts using f-and-m-algebras

– f-algebras for a functor f describe the pure parts of an effectful data type – m-Eilenberg-Moore algebras for a monad m describe the effects

  • Represent: Effectful data types as initial f-and-m-algebras
  • Show: Initial f-and-m-algebra techniques are at the right level of ab-

straction for effectful data types

slide-24
SLIDE 24

Structure of This Talk

  • Recall: Standard initial algebra techniques
  • Argue: Straightforward application of initial algebra techniques is at

the wrong level of abstraction for effectful data types

  • Instead: Separate pure and effectful parts using f-and-m-algebras

– f-algebras for a functor f describe the pure parts of an effectful data type – m-Eilenberg-Moore algebras for a monad m describe the effects

  • Represent: Effectful data types as initial f-and-m-algebras
  • Show: Initial f-and-m-algebra techniques are at the right level of ab-

straction for effectful data types

  • Revisit: Motivating examples with initial f-and-m-algebra techniques
slide-25
SLIDE 25

Initial Algebras for Pure Data Types (I)

  • Model the individual “layers” of a data type using a functor

(f, fmap :: (a → b) → f a → f b) Here, fmap is assumed to preserve identities and composition

slide-26
SLIDE 26

Initial Algebras for Pure Data Types (I)

  • Model the individual “layers” of a data type using a functor

(f, fmap :: (a → b) → f a → f b) Here, fmap is assumed to preserve identities and composition

  • Describe how to reduce each “layer” in an inductive data structure to

a value using an f-algebra (a, k :: f a → a)

slide-27
SLIDE 27

Initial Algebras for Pure Data Types (I)

  • Model the individual “layers” of a data type using a functor

(f, fmap :: (a → b) → f a → f b) Here, fmap is assumed to preserve identities and composition

  • Describe how to reduce each “layer” in an inductive data structure to

a value using an f-algebra (a, k :: f a → a)

  • Characterize the data type as the carrier µf of the initial f-algebra

(µf, in : f(µf) → µf)

slide-28
SLIDE 28

Initial Algebras for Pure Data Types (II)

  • An f-algebra homomorphism from an f-algebra (a, ka) to an f-algebra

(b, kb) is a function h :: a → b such that f a

fmap h

  • ka
  • f b

kb

  • a

h

b

slide-29
SLIDE 29

Initial Algebras for Pure Data Types (II)

  • An f-algebra homomorphism from an f-algebra (a, ka) to an f-algebra

(b, kb) is a function h :: a → b such that f a

fmap h

  • ka
  • f b

kb

  • a

h

b

  • For every f-algebra (a, k), there is a unique f-algebra homomorphism

from the initial f-algebra (µf, in) to (a, k) f(µf)

fmap ( |k| )

  • in
  • f a

k

  • µf

( |k| )

a

slide-30
SLIDE 30

Initial Algebras for Pure Data Types (II)

  • An f-algebra homomorphism from an f-algebra (a, ka) to an f-algebra

(b, kb) is a function h :: a → b such that f a

fmap h

  • ka
  • f b

kb

  • a

h

b

  • For every f-algebra (a, k), there is a unique f-algebra homomorphism

from the initial f-algebra (µf, in) to (a, k) f(µf)

fmap ( |k| )

  • in
  • f a

k

  • µf

( |k| )

a

  • We denote the unique function from µf to a by (

|k| )

slide-31
SLIDE 31

Example I — Initial Algebras for Lists

  • The functor ListF a describes the individual “layers” of a list

data ListF a x = Nil | Cons a x fmap :: (x → y) → ListF a x → ListF a y fmap g Nil = Nil fmap g (Cons a xs) = Cons a (g xs)

slide-32
SLIDE 32

Example I — Initial Algebras for Lists

  • The functor ListF a describes the individual “layers” of a list

data ListF a x = Nil | Cons a x fmap :: (x → y) → ListF a x → ListF a y fmap g Nil = Nil fmap g (Cons a xs) = Cons a (g xs)

  • The type [a] of finite lists is the carrier of the initial (ListF a)-algebra

with in :: ListF a [a] → [a] in Nil = [ ] in (Cons a xs) = a : xs

slide-33
SLIDE 33

Example I — Initial Algebras for Lists

  • The functor ListF a describes the individual “layers” of a list

data ListF a x = Nil | Cons a x fmap :: (x → y) → ListF a x → ListF a y fmap g Nil = Nil fmap g (Cons a xs) = Cons a (g xs)

  • The type [a] of finite lists is the carrier of the initial (ListF a)-algebra

with in :: ListF a [a] → [a] in Nil = [ ] in (Cons a xs) = a : xs

  • The fold for [a] is

( | − | ) :: (ListF a b → b) → [a] → b ( |k| ) [ ] = k Nil ( |k| ) (a : xs) = k (Cons a (( |k| ) xs))

slide-34
SLIDE 34

Example II — Initial Algebras Generically

  • The carrier of the initial f-algebra for a functor (f, fmap) can be

implemented as data Mu f = In {unIn :: f (Mu f)}

slide-35
SLIDE 35

Example II — Initial Algebras Generically

  • The carrier of the initial f-algebra for a functor (f, fmap) can be

implemented as data Mu f = In {unIn :: f (Mu f)}

  • The type Mu f is the carrier of the initial f-algebra with

in :: f (Mu f) → Mu f in = In

slide-36
SLIDE 36

Example II — Initial Algebras Generically

  • The carrier of the initial f-algebra for a functor (f, fmap) can be

implemented as data Mu f = In {unIn :: f (Mu f)}

  • The type Mu f is the carrier of the initial f-algebra with

in :: f (Mu f) → Mu f in = In

  • The fold for Mu f can be defined as

( | − | ) :: Functor f ⇒ (f a → a) → Mu f → a ( |k| ) = k ◦ fmap ( |k| ) ◦ unIn

slide-37
SLIDE 37

What Have We Gained?

  • Definitional principles for defining functions on data types

– fold operators for expressing recursive functions – definition by pattern matching

slide-38
SLIDE 38

What Have We Gained?

  • Definitional principles for defining functions on data types

– fold operators for expressing recursive functions – definition by pattern matching

  • Proof principles for reasoning about such functions

– induction rules – fold fusion rules

slide-39
SLIDE 39

What Have We Gained?

  • Definitional principles for defining functions on data types

– fold operators for expressing recursive functions – definition by pattern matching

  • Proof principles for reasoning about such functions

– fold fusion rules – induction rules

  • Other tools for structured programming and reasoning — e.g., intro-

duction and elimination rules, computation (i.e., β, from weak initial- ity) rules and extensionality (i.e., η, from uniqueness) rules for folds; build combinators; fold/build rules...

slide-40
SLIDE 40

What Have We Gained?

  • Definitional principles for defining functions on data types

– fold operators for expressing recursive functions – definition by pattern matching

  • Proof principles for reasoning about such functions

– fold fusion rules – induction rules

  • Other tools for structured programming and reasoning — e.g., intro-

duction and elimination rules, computation (i.e., β, from weak initial- ity) rules and extensionality (i.e., η, from uniqueness) rules for folds; build combinators; fold/build rules... Above all, initial algebra semantics gives a principled approach to pro- gramming with data types that is generic over data types

slide-41
SLIDE 41

Exploiting Initiality

Proof Principle 1 Let (a, k) be an f-algebra and g : µf → a be a function. The equation ( |k| ) = g holds iff g is an f-algebra homomorphism, i.e., iff g ◦ in = k ◦ fmap g f(µf)

fmap g in

  • f a

k

  • µf

g

a

slide-42
SLIDE 42

Representing append

  • Assume (µ(ListF a), in) exists
slide-43
SLIDE 43

Representing append

  • Assume (µ(ListF a), in) exists
  • We can define append in terms of fold as

append :: µ(ListF a) → µ(ListF a) → µ(ListF a) append xs ys = ( |k| ) xs where k Nil = ys k (Cons a xs) = in (Cons a xs)

slide-44
SLIDE 44

Representing append

  • Assume (µ(ListF a), in) exists
  • We can define append in terms of fold as

append :: µ(ListF a) → µ(ListF a) → µ(ListF a) append xs ys = ( |k| ) xs where k Nil = ys k (Cons a xs) = in (Cons a xs)

  • Unfolding this definition gives these equational properties of append

append (in Nil) ys = ys append (in (Cons a xs)) ys = in (Cons a (append xs ys))

slide-45
SLIDE 45

Associativity of append (I)

Theorem: For all xs, ys, zs :: µ(ListF a), append xs (append ys zs) = append (append xs ys) zs

slide-46
SLIDE 46

Associativity of append (I)

Theorem: For all xs, ys, zs :: µ(ListF a), append xs (append ys zs) = append (append xs ys) zs Proof:

  • 1. Instantiate Proof Principle 1 and prove the equation

( |k| ) xs = append (append xs ys) zs

slide-47
SLIDE 47

Associativity of append (I)

Theorem: For all xs, ys, zs :: µ(ListF a), append xs (append ys zs) = append (append xs ys) zs Proof:

  • 1. Instantiate Proof Principle 1 and prove the equation

( |k| ) xs = append (append xs ys) zs i.e., ( |k| ) = g where g = λxs. append (append xs ys) zs k Nil = append ys zs k (Cons a xs) = in (Cons a xs)

slide-48
SLIDE 48

Associativity of append (II)

  • 2. It suffices to prove that

g ◦ in = k ◦ fmap g i.e., that for all x :: ListF a (µ(ListF a)), = append (append (in x) ys) zs = k (fmap (λxs. append (append xs ys) zs) x)

slide-49
SLIDE 49

Associativity of append (II)

  • 2. It suffices to prove that

g ◦ in = k ◦ fmap g i.e., that for all x :: ListF a (µ(ListF a)), = append (append (in x) ys) zs = k (fmap (λxs. append (append xs ys) zs) x)

  • 3. Use case analysis according as x = Nil or x = Cons a xs
slide-50
SLIDE 50

Associativity of append (II)

  • 2. It suffices to prove that

g ◦ in = k ◦ fmap g i.e., that for all x :: ListF a (µ(ListF a)), = append (append (in x) ys) zs = k (fmap (λxs. append (append xs ys) zs) x)

  • 3. Use case analysis according as x = Nil or x = Cons a xs
  • 4. For each case, we directly use the equational properties of append and

the definitions of g and fmap for ListF a

slide-51
SLIDE 51

Associativity of append (II)

  • 2. It suffices to prove that

g ◦ in = k ◦ fmap g i.e., that for all x :: ListF a (µ(ListF a)), = append (append (in x) ys) zs = k (fmap (λxs. append (append xs ys) zs) x)

  • 3. Use case analysis according as x = Nil or x = Cons a xs
  • 4. For each case, we directly use the equational properties of append and

the definitions of g and fmap for ListF a The proof is straightforward, easy, and short (9 lines)

slide-52
SLIDE 52

Monads for Effects

  • Model an effect using a monad

(m, fmapm, returnm, joinm) where fmapm :: (a → b) → m a → m b returnm :: a → m a joinm :: m (m a) → m a

slide-53
SLIDE 53

Monads for Effects

  • Model an effect using a monad

(m, fmapm, returnm, joinm) where fmapm :: (a → b) → m a → m b returnm :: a → m a joinm :: m (m a) → m a

  • The monad laws must be satisfied
slide-54
SLIDE 54

Monads for Effects

  • Model an effect using a monad

(m, fmapm, returnm, joinm) where fmapm :: (a → b) → m a → m b returnm :: a → m a joinm :: m (m a) → m a

  • The monad laws must be satisfied
  • The naturality laws for returnm and joinm must be satisfied
slide-55
SLIDE 55

Monads for Effects

  • Model an effect using a monad

(m, fmapm, returnm, joinm) where fmapm :: (a → b) → m a → m b returnm :: a → m a joinm :: m (m a) → m a

  • The monad laws must be satisfied
  • The naturality laws for returnm and joinm must be satisfied
  • Examples are the non-termination monad (−)⊥, the IO monad, the

error monad, the continuations monad, etc.

slide-56
SLIDE 56

Monad Morphisms

A monad morphism from (m1, fmapm1 , returnm1, joinm1 ) to (m2, fmapm2 , returnm2, joinm2) is a function h :: m1 a → m2 a that preserves fmaps, returns, and joins h ◦ fmapm1 g = fmapm2 g ◦ h h ◦ returnm1 = returnm2 h ◦ joinm1 = joinm2 ◦ h ◦ fmapm1 h

slide-57
SLIDE 57

Effectful Lists

  • A common generalization of Listio and Listlazy a is

data List′ m a newtype List m a = = Nilm | Consm a (List m a) List (m (List′ m a))

slide-58
SLIDE 58

Effectful Lists

  • A common generalization of Listio and Listlazy a is

data List′ m a newtype List m a = = Nilm | Consm a (List m a) List (m (List′ m a))

  • A further generalization replaces list constructors with an arbitrary

functor f that describes the data to be interleaved with the effects of the monad m: data MuFM ′ f m newtype MuFM f m = = In (f (MuFM f m)) Mu (m (MuFM ′ f m))

slide-59
SLIDE 59

Effectful Lists

  • A common generalization of Listio and Listlazy a is

data List′ m a newtype List m a = = Nilm | Consm a (List m a) List (m (List′ m a))

  • A further generalization replaces list constructors with an arbitrary

functor f that describes the data to be interleaved with the effects of the monad m: data MuFM ′ f m newtype MuFM f m = = In (f (MuFM f m)) Mu (m (MuFM ′ f m))

  • MuFM represents a pure inductive type described by f interleaved

with effects given by m

slide-60
SLIDE 60

An Append Function for Effectful Lists

  • Assume (µ(ListF a ◦ m), in) exists
slide-61
SLIDE 61

An Append Function for Effectful Lists

  • Assume (µ(ListF a ◦ m), in) exists
  • List m a is isomorphic to m (µ(ListF a ◦ m))
slide-62
SLIDE 62

An Append Function for Effectful Lists

  • Assume (µ(ListF a ◦ m), in) exists
  • List m a is isomorphic to m (µ(ListF a ◦ m))
  • We can define eAppend by

eAppend :: m (µ(ListF a ◦ m)) → m (µ(ListF a ◦ m)) → m (µ(ListF a ◦ m)) eAppend xs ys = joinm (fmapm ( |k| ) xs) where k Nil = ys k (Cons a xs) = returnm (in (Cons a (joinm xs)))

slide-63
SLIDE 63

An Append Function for Effectful Lists

  • Assume (µ(ListF a ◦ m), in) exists
  • List m a is isomorphic to m (µ(ListF a ◦ m))
  • We can define eAppend by

eAppend :: m (µ(ListF a ◦ m)) → m (µ(ListF a ◦ m)) → m (µ(ListF a ◦ m)) eAppend xs ys = joinm (fmapm ( |k| ) xs) where k Nil = ys k (Cons a xs) = returnm (in (Cons a (joinm xs)))

  • This is similar to the definition of append, but we have had to insert

uses of the monadic structure returnm, joinm and fmapm because the initial f-algebra is unaware of the presence of effects

slide-64
SLIDE 64

Equational Properties of eAppend

  • Unfolding the definitions gives these equational properties of eAppend

eAppend (returnm (in Nil)) ys = ys eAppend (returnm (in (Cons a xs))) ys = returnm (in (Cons a (eAppend xs ys)))

slide-65
SLIDE 65

Equational Properties of eAppend

  • Unfolding the definitions gives these equational properties of eAppend

eAppend (returnm (in Nil)) ys = ys eAppend (returnm (in (Cons a xs))) ys = returnm (in (Cons a (eAppend xs ys)))

  • Deriving these properties takes more work than in the pure case be-

cause we have to shuffle the returnm, joinm, and fmapm around in

  • rder to apply the monad laws
slide-66
SLIDE 66

Equational Properties of eAppend

  • Unfolding the definitions gives these equational properties of eAppend

eAppend (returnm (in Nil)) ys = ys eAppend (returnm (in (Cons a xs))) ys = returnm (in (Cons a (eAppend xs ys)))

  • Deriving these properties takes more work than in the pure case be-

cause we have to shuffle the returnm, joinm, and fmapm around in

  • rder to apply the monad laws
  • Whenever we use initial f-algebras to define functions on data types

with interleaved effects, we will repeat this kind of work over again

slide-67
SLIDE 67

Equational Properties of eAppend

  • Unfolding the definitions gives these equational properties of eAppend

eAppend (returnm (in Nil)) ys = ys eAppend (returnm (in (Cons a xs))) ys = returnm (in (Cons a (eAppend xs ys)))

  • Deriving these properties takes more work than in the pure case be-

cause we have to shuffle the returnm, joinm, and fmapm around in

  • rder to apply the monad laws
  • Whenever we use initial f-algebras to define functions on data types

with interleaved effects, we will repeat this kind of work over again

  • When we try to prove associativity of eAppend we will be unable to

directly use these properties as we did in the uneffectful proof because we are forced to unfold the definition of eAppend to apply PP1

slide-68
SLIDE 68

Associativity of eAppend (I)

Theorem: For all xs, ys, zs :: m (µ(ListF a ◦ m)), eAppend xs (eAppend ys zs) = eAppend (eAppend xs ys) zs

slide-69
SLIDE 69

Associativity of eAppend (I)

Theorem: For all xs, ys, zs :: m (µ(ListF a ◦ m)), eAppend xs (eAppend ys zs) = eAppend (eAppend xs ys) zs Proof:

  • 1. Unfold the definition of eAppend to rewrite LHS to

joinm (fmapm (( |keAppend ys zs| )) xs) Here, kl is the instance of the function k defined in the body of eAppend with the free variable ys replaced by l.

slide-70
SLIDE 70

Associativity of eAppend (I)

Theorem: For all xs, ys, zs :: m (µ(ListF a ◦ m)), eAppend xs (eAppend ys zs) = eAppend (eAppend xs ys) zs Proof:

  • 1. Unfold the definition of eAppend to rewrite LHS to

joinm (fmapm (( |keAppend ys zs| )) xs) Here, kl is the instance of the function k defined in the body of eAppend with the free variable ys replaced by l.

  • 2. Use the definition of eAppend (thrice!), plus naturality of joinm, the

third monad law, and the fact that fmapm preserves composition to rewrite RHS to joinm (fmapm ((λl. eAppend l zs) ◦ ( |kys| )) xs)

slide-71
SLIDE 71

Associativity of eAppend (II)

  • 3. Instantiate Proof Principle 1 and prove the equation

( |keAppend ys zs| ) = (λl. eAppend l zs) ◦ ( |kys| )

slide-72
SLIDE 72

Associativity of eAppend (II)

  • 3. Instantiate Proof Principle 1 and prove the equation

( |keAppend ys zs| ) = (λl. eAppend l zs) ◦ ( |kys| )

  • 4. It suffices to prove that for all x :: ListF a (m (µ(ListF a ◦ m)))

eAppend (( |kys| ) (in x)) zs = keAppend xs ys (fmapListF a (fmapm ((λl. eAppend l zs) ◦ ( |kys| ))) x)

slide-73
SLIDE 73

Associativity of eAppend (II)

  • 3. Instantiate Proof Principle 1 and prove the equation

( |keAppend ys zs| ) = (λl. eAppend l zs) ◦ ( |kys| )

  • 4. It suffices to prove that for all x :: ListF a (m (µ(ListF a ◦ m)))

eAppend (( |kys| ) (in x)) zs = keAppend xs ys (fmapListF a (fmapm ((λl. eAppend l zs) ◦ ( |kys| ))) x)

  • 5. Use case analysis according as x = Nil or x = Cons a xs
slide-74
SLIDE 74

Associativity of eAppend (II)

  • 3. Instantiate Proof Principle 1 and prove the equation

( |keAppend ys zs| ) = (λl. eAppend l zs) ◦ ( |kys| )

  • 4. It suffices to prove that for all x :: ListF a (m (µ(ListF a ◦ m)))

eAppend (( |kys| ) (in x)) zs = keAppend xs ys (fmapListF a (fmapm ((λl. eAppend l zs) ◦ ( |kys| ))) x)

  • 5. Use case analysis according as x = Nil or x = Cons a xs
  • 6. For each case, use the definitions of eAppend, fmapListF a, and the

instances of k; the fact that ( |h| ) is a (ListF a ◦ m)-algebra homomor- phism for all h; the naturality of joinm; the fact that fmapm preserves composition; and the third monad law

slide-75
SLIDE 75

Associativity of eAppend (II)

  • 3. Instantiate Proof Principle 1 and prove the equation

( |keAppend ys zs| ) = (λl. eAppend l zs) ◦ ( |kys| )

  • 4. It suffices to prove that for all x :: ListF a (m (µ(ListF a ◦ m)))

eAppend (( |kys| ) (in x)) zs = keAppend xs ys (fmapListF a (fmapm ((λl. eAppend l zs) ◦ ( |kys| ))) x)

  • 5. Use case analysis according as x = Nil or x = Cons a xs
  • 6. For each case, use the definitions of eAppend, fmapListF a, and the

instances of k; the fact that ( |h| ) is a (ListF a ◦ m)-algebra homomor- phism for all h; the naturality of joinm; the fact that fmapm preserves composition; and the third monad law The proof is upwards of 25 (complicated) lines long!

slide-76
SLIDE 76

Problems and Alternatives

  • Problems:
  • 1. Requires non-trivial rewriting in order to apply Proof Principle 1
slide-77
SLIDE 77

Problems and Alternatives

  • Problems:
  • 1. Requires non-trivial rewriting in order to apply Proof Principle 1
  • 2. Requires multiple unfoldings of the definition of eAppend to pro-

ceed, forcing calculations to be repeated, preventing equational properties from being used, breaking abstraction layers, ...

slide-78
SLIDE 78

Problems and Alternatives

  • Problems:
  • 1. Requires non-trivial rewriting in order to apply Proof Principle 1
  • 2. Requires multiple unfoldings of the definition of eAppend to pro-

ceed, forcing calculations to be repeated, preventing equational properties from being used, breaking abstraction layers, ...

  • Alternatives:
  • 1. Use eAppend xs ys = extend ((

|kys| ) xs), where extend is the (argument- flipped) bind operation for m for quicker reduction to Proof Prin- ciple 1

slide-79
SLIDE 79

Problems and Alternatives

  • Problems:
  • 1. Requires non-trivial rewriting in order to apply Proof Principle 1
  • 2. Requires multiple unfoldings of the definition of eAppend to pro-

ceed, forcing calculations to be repeated, preventing equational properties from being used, breaking abstraction layers, ...

  • Alternatives:
  • 1. Use eAppend xs ys = extend ((

|kys| ) xs), where extend is the (argument- flipped) bind operation for m for quicker reduction to Proof Prin- ciple 1

  • 2. Use fold fusion to prove the goal in bullet point 3 to save effort
slide-80
SLIDE 80

Problems and Alternatives

  • Problems:
  • 1. Requires non-trivial rewriting in order to apply Proof Principle 1
  • 2. Requires multiple unfoldings of the definition of eAppend to pro-

ceed, forcing calculations to be repeated, preventing equational properties from being used, breaking abstraction layers, ...

  • Alternatives:
  • 1. Use eAppend xs ys = extend ((

|kys| ) xs), where extend is the (argument- flipped) bind operation for m for quicker reduction to Proof Prin- ciple 1

  • 2. Use fold fusion to prove the goal in bullet point 3 to save effort
  • But we still have to unfold the definition of eAppend and reason using

the monad laws, and the pure and effectful parts of the proof still aren’t

  • separated. Most importantly, we still cannot reuse the reasoning from

the proof for the pure case!

slide-81
SLIDE 81

Separating Data and Effects

  • Use f-and-m-algebras, i.e., f-algebras that are simultaneously m-

Eilenberg-Moore algebras

slide-82
SLIDE 82

Separating Data and Effects

  • Use f-and-m-algebras, i.e., f-algebras that are simultaneously m-

Eilenberg-Moore algebras

  • An m-Eilenberg-Moore algebra for a type a describes how to properly

incorporate the effects of the monad m into values of type a

slide-83
SLIDE 83

Separating Data and Effects

  • Use f-and-m-algebras, i.e., f-algebras that are simultaneously m-

Eilenberg-Moore algebras

  • An m-Eilenberg-Moore algebra for a type a describes how to properly

incorporate the effects of the monad m into values of type a

  • The f-algebra part handles the pure parts of the structure
slide-84
SLIDE 84

Separating Data and Effects

  • Use f-and-m-algebras, i.e., f-algebras that are simultaneously m-

Eilenberg-Moore algebras

  • An m-Eilenberg-Moore algebra for a type a describes how to properly

incorporate the effects of the monad m into values of type a

  • The f-algebra part handles the pure parts of the structure
  • The m-Eilenberg-Moore-algebra part handles the effectful parts, ac-

counting for – the correct preservation of potential lack of effects (through the preservation of return) – the potential merging of effects present between layers of the pure datatype (through the preservation of join)

slide-85
SLIDE 85

m-Eilenberg-Moore Algebras

  • An m-Eilenberg-Moore algebra is a pair

(a, l :: m a → a) such that l preserves the return and join monad structure a

returnm

  • id
  • m a

l

  • a

m (m a)

joinm fmapm l

  • m a

l

  • m a

i

a

slide-86
SLIDE 86

m-Eilenberg-Moore Algebras

  • An m-Eilenberg-Moore algebra is a pair

(a, l :: m a → a) such that l preserves the return and join monad structure a

returnm

  • id
  • m a

l

  • a

m (m a)

joinm fmapm l

  • m a

l

  • m a

i

a

  • An m-Eilenberg-Moore algebra homomorphism is an m-algebra homo-

morphism

slide-87
SLIDE 87

f-and-m-Algebras

  • An f-and-m-algebra is a triple

(a, k, l) where k :: f a → a l :: m a → a and l is an m-Eilenberg-Moore algebra

slide-88
SLIDE 88

f-and-m-Algebras

  • An f-and-m-algebra is a triple

(a, k, l) where k :: f a → a l :: m a → a and l is an m-Eilenberg-Moore algebra

  • An f-and-m-algebra homomorphism from (a, ka, la) to (b, kb, lb) is a

function h :: a → b that is simultaneously an f-algebra homomorphism and an m-algebra homomorphism h ◦ ka = kb ◦ fmapf h h ◦ la = lb ◦ fmapm h

slide-89
SLIDE 89

Initial f-and-m-Algebras

  • We write (µ(f|m), inf, inm) for the initial f-and-m-algebra
slide-90
SLIDE 90

Initial f-and-m-Algebras

  • We write (µ(f|m), inf, inm) for the initial f-and-m-algebra
  • For every f-and-m-algebra (a, k, l) there is a unique f-and-m-algebra

homomorphism from the initial f-and-m-algebra (µ(f|m), inf, inm) to (a, k, l) f(µ(f|m))

fmapf ( |k|l| ) inf

  • f a

k

  • m(µ(f|m))

fmapm ( |k|l| )

  • inm
  • m a

l

  • µ(f|m)

( |k|l| )

a

µ(f|m)

( |k|l| )

a

slide-91
SLIDE 91

Initial f-and-m-Algebras

  • We write (µ(f|m), inf, inm) for the initial f-and-m-algebra
  • For every f-and-m-algebra (a, k, l) there is a unique f-and-m-algebra

homomorphism from the initial f-and-m-algebra (µ(f|m), inf, inm) to (a, k, l) f(µ(f|m))

fmapf ( |k|l| ) inf

  • f a

k

  • m(µ(f|m))

fmapm ( |k|l| )

  • inm
  • m a

l

  • µ(f|m)

( |k|l| )

a

µ(f|m)

( |k|l| )

a

  • We denote the unique function from µ(f|m) to a by (

|k|l| )

slide-92
SLIDE 92

A Proof Principle for Effectful Data Types

  • Proof Principle 2 Let (a, k, l) be an f-and-m-algebra and g : µ(f|m) →

a be a function. The equation ( |k|l| ) = g holds iff g is simultaneously an f-algebra homomorphism and an m- algebra homomorphism

slide-93
SLIDE 93

A Proof Principle for Effectful Data Types

  • Proof Principle 2 Let (a, k, l) be an f-and-m-algebra and g : µ(f|m) →

a be a function. The equation ( |k|l| ) = g holds iff g is simultaneously an f-algebra homomorphism and an m- algebra homomorphism, i.e., iff g ◦ inf = k ◦ fmapf g and g ◦ inm = l ◦ fmapm g

slide-94
SLIDE 94

A Proof Principle for Effectful Data Types

  • Proof Principle 2 Let (a, k, l) be an f-and-m-algebra and g : µ(f|m) →

a be a function. The equation ( |k|l| ) = g holds iff g is simultaneously an f-algebra homomorphism and an m- algebra homomorphism, i.e., iff g ◦ inf = k ◦ fmapf g and g ◦ inm = l ◦ fmapm g

  • Proof Principle 2 cleanly splits the pure and effectful proof obligations!
slide-95
SLIDE 95

Representing List m a

  • Our data type

data List′ m a newtype List m a = = Nilm | Consm a (List m a) List (m (List′ m a)) can be represented as the carrier µ(ListF a|m) of the initial (ListF a)- and-m-algebra

slide-96
SLIDE 96

Representing List m a

  • Our data type

data List′ m a newtype List m a = = Nilm | Consm a (List m a) List (m (List′ m a)) can be represented as the carrier µ(ListF a|m) of the initial (ListF a)- and-m-algebra with inListF a :: ListF a (List m a) → List m a inListF a Nil = List (returnm Nilm) inListF a (Cons a xs) = List (returnm (Consm a xs))

slide-97
SLIDE 97

Representing List m a

  • Our data type

data List′ m a newtype List m a = = Nilm | Consm a (List m a) List (m (List′ m a)) can be represented as the carrier µ(ListF a|m) of the initial (ListF a)- and-m-algebra with inListF a :: ListF a (List m a) → List m a inListF a Nil = List (returnm Nilm) inListF a (Cons a xs) = List (returnm (Consm a xs)) and inm :: m (List m a) → List m a inm ml = List (do {List x ← ml; x})

slide-98
SLIDE 98

Representing List m a

  • Our data type

data List′ m a newtype List m a = = Nilm | Consm a (List m a) List (m (List′ m a)) can be represented as the carrier µ(ListF a|m) of the initial (ListF a)- and-m-algebra with inListF a :: ListF a (List m a) → List m a inListF a Nil = List (returnm Nilm) inListF a (Cons a xs) = List (returnm (Consm a xs)) and inm :: m (List m a) → List m a inm ml = List (do {List x ← ml; x})

  • If not for the List constructor, inm would be join
slide-99
SLIDE 99

A fold for List m a

The fold for µ (ListF a|m) is defined as a pair of mutually recursive func- tions, following the structure of the declaration of List m a: ( | − | − | ) :: (ListF a b → b) → (m b → b) → List m a → b ( |k|l| ) = loop where loop :: List m a → b loop (List x) = l (fmapm loop′ x) loop′ :: List′ m a → b loop′ Nilm = k Nil loop′ (Consm a xs) = k (Cons a (loop xs))

slide-100
SLIDE 100

Representing eAppend (Again)

  • Assume (µ(ListF a|m), inListF a, inm) exists
slide-101
SLIDE 101

Representing eAppend (Again)

  • Assume (µ(ListF a|m), inListF a, inm) exists
  • We can define eAppend by:

eAppend :: µ(ListF a|m) → µ(ListF a|m) → µ(ListF a|m) eAppend xs ys = ( |k|inm| ) xs where k Nil = ys k (Cons a xs) = inListF a (Cons a xs)

slide-102
SLIDE 102

Representing eAppend (Again)

  • Assume (µ(ListF a|m), inListF a, inm) exists
  • We can define eAppend by:

eAppend :: µ(ListF a|m) → µ(ListF a|m) → µ(ListF a|m) eAppend xs ys = ( |k|inm| ) xs where k Nil = ys k (Cons a xs) = inListF a (Cons a xs)

  • This is identical to the definition of pure append, except that

– inm is an additional argument to the fold

slide-103
SLIDE 103

Representing eAppend (Again)

  • Assume (µ(ListF a|m), inListF a, inm) exists
  • We can define eAppend by:

eAppend :: µ(ListF a|m) → µ(ListF a|m) → µ(ListF a|m) eAppend xs ys = ( |k|inm| ) xs where k Nil = ys k (Cons a xs) = inListF a (Cons a xs)

  • This is identical to the definition of pure append, except that

– inm is an additional argument to the fold – inListF a :: ListF a (List m a) → List m a (not ListF a [a] → [a])

slide-104
SLIDE 104

Representing eAppend (Again)

  • Assume (µ(ListF a|m), inListF a, inm) exists
  • We can define eAppend by:

eAppend :: µ(ListF a|m) → µ(ListF a|m) → µ(ListF a|m) eAppend xs ys = ( |k|inm| ) xs where k Nil = ys k (Cons a xs) = inListF a (Cons a xs)

  • This is identical to the definition of pure append, except that

– inm is an additional argument to the fold – inListF a :: ListF a (List m a) → List m a (not ListF a [a] → [a])

  • In particular, the pure function k is — except for types — identical to

the local function in append

slide-105
SLIDE 105

Equational Properties of eAppend (Again)

  • Unfolding the definitions and using the fact that (

|k|inm| ) is an f-and- m-algebra homomorphism gives these equational properties, which are identical — except for types — to the ones for append eAppend (inListF a Nil) ys = ys eAppend (inListF a (Cons a xs)) ys = inListF a (Cons a (eAppend xs ys))

slide-106
SLIDE 106

Equational Properties of eAppend (Again)

  • Unfolding the definitions and using the fact that (

|k|inm| ) is an f-and- m-algebra homomorphism gives these equational properties, which are identical — except for types — to the ones for append eAppend (inListF a Nil) ys = ys eAppend (inListF a (Cons a xs)) ys = inListF a (Cons a (eAppend xs ys))

  • Moreover, for any fixed ys, λxs. eAppend xs ys is an m-Eilenberg-

Moore homomorphism. So for all x :: m (µ(ListF a|m)) eAppend (inm x) ys = inm (fmapm (λxs. eAppend xs ys) x)

slide-107
SLIDE 107

Equational Properties of eAppend (Again)

  • Unfolding the definitions and using the fact that (

|k|inm| ) is an f-and- m-algebra homomorphism gives these equational properties, which are identical — except for types — to the ones for append eAppend (inListF a Nil) ys = ys eAppend (inListF a (Cons a xs)) ys = inListF a (Cons a (eAppend xs ys))

  • Moreover, for any fixed ys, λxs. eAppend xs ys is an m-Eilenberg-

Moore homomorphism. So for all x :: m (µ(ListF a|m)) eAppend (inm x) ys = inm (fmapm (λxs. eAppend xs ys) x)

  • Unfolding the definition of inm we see that eAppend always evaluates

the effects placed “before” the first element of its first argument

slide-108
SLIDE 108

Associativity of eAppend (Again) (I)

Theorem: For all xs, ys, zs :: µ(ListF a|m), eAppend xs (eAppend ys zs) = eAppend (eAppend xs ys) zs

slide-109
SLIDE 109

Associativity of eAppend (Again) (I)

Theorem: For all xs, ys, zs :: µ(ListF a|m), eAppend xs (eAppend ys zs) = eAppend (eAppend xs ys) zs Proof:

  • 1. Instantiate Proof Principle 2 and prove the equation

( |k|inm| ) xs = eAppend (eAppend xs ys) zs

slide-110
SLIDE 110

Associativity of eAppend (Again) (I)

Theorem: For all xs, ys, zs :: µ(ListF a|m), eAppend xs (eAppend ys zs) = eAppend (eAppend xs ys) zs Proof:

  • 1. Instantiate Proof Principle 2 and prove the equation

( |k|inm| ) xs = eAppend (eAppend xs ys) zs i.e., ( |k|inm| ) = g where g = λxs. eAppend (eAppend xs ys) zs k Nil = eAppend ys zs k (Cons a xs) = inListF a (Cons a xs)

slide-111
SLIDE 111

Associativity of eAppend (Again) (II)

  • 2. It suffices to prove that for all x :: ListF a (µ(ListF a|m)),

eAppend (eAppend (inListF a x) ys) zs = k (fmapListF a (λxs. eAppend (eAppend xs ys) zs) x) and eAppend (eAppend (inm x) ys) zs = inm (fmapm (λxs. eAppend (eAppend xs ys) zs) x)

slide-112
SLIDE 112

Associativity of eAppend (Again) (III)

  • 3. The first is — up to renaming and types — exactly the same as the

equation we had to show for pure append and is proved using the first two equational properties of eAppend

slide-113
SLIDE 113

Associativity of eAppend (Again) (III)

  • 3. The first is — up to renaming and types — exactly the same as the

equation we had to show for pure append and is proved using the first two equational properties of eAppend

  • 4. The second is proved in just 4 lines using the third equational property
  • f eAppend (i.e., that λxs. eAppend xs ys is an m-Eilenberg-Moore ho-

momorphism for any fixed ys), and the facts that such homomorphisms are closed under composition and that fmapm preserves composition

slide-114
SLIDE 114

Associativity of eAppend (Again) (III)

  • 3. The first is — up to renaming and types — exactly the same as the

equation we had to show for pure append and is proved using the first two equational properties of eAppend

  • 4. The second is proved in just 4 lines using the third equational property
  • f eAppend (i.e., that λxs. eAppend xs ys is an m-Eilenberg-Moore ho-

momorphism for any fixed ys), and the facts that such homomorphisms are closed under composition and that fmapm preserves composition The separation of pure and effectful parts ensures that we can reuse the proof for append, so only have to establish the side condition for effects

slide-115
SLIDE 115

Associativity of eAppend (Again) (III)

  • 3. The first is — up to renaming and types — exactly the same as the

equation we had to show for pure append and is proved using the first two equational properties of eAppend

  • 4. The second is proved in just 4 lines using the third equational property
  • f eAppend (i.e., that λxs. eAppend xs ys is an m-Eilenberg-Moore ho-

momorphism for any fixed ys), and the facts that such homomorphisms are closed under composition and that fmapm preserves composition The separation of pure and effectful parts ensures that we can reuse the proof for append, so only have to establish the side condition for effects This proof is simpler, shorter, and more intuitive than the f-algebra proof!

slide-116
SLIDE 116

Limitations

  • Proof Principle 2 fails for proving

eReverse (eAppend xs ys) = eAppend (eReverse ys) (eReverse xs) for a suitably defined eReverse :: µ(ListF a|m) → µ(ListF a|m)

slide-117
SLIDE 117

Limitations

  • Proof Principle 2 fails for proving

eReverse (eAppend xs ys) = eAppend (eReverse ys) (eReverse xs) for a suitably defined eReverse :: µ(ListF a|m) → µ(ListF a|m)

  • Intuitively, the LHS will execute all the effects of xs, then those of ys,

while the RHS will execute all the effects of ys, then those of xs

slide-118
SLIDE 118

Limitations

  • Proof Principle 2 fails for proving

eReverse (eAppend xs ys) = eAppend (eReverse ys) (eReverse xs) for a suitably defined eReverse :: µ(ListF a|m) → µ(ListF a|m)

  • Intuitively, the LHS will execute all the effects of xs, then those of ys,

while the RHS will execute all the effects of ys, then those of xs

  • Technically, the problem is that λxs. eAppend (eReverse ys) (eReverse xs)

is not an m-Eilenberg-Moore-algebra homomorphism for all ys

slide-119
SLIDE 119

f-and-m-Algebras for Interleaved Non-termination

  • The interleaving of data and non-termination effects can be made

explicit using initial f-and-m-algebras by taking m to be the non- termination monad

slide-120
SLIDE 120

f-and-m-Algebras for Interleaved Non-termination

  • The interleaving of data and non-termination effects can be made

explicit using initial f-and-m-algebras by taking m to be the non- termination monad

  • In particular, the type Listlazy is µ(ListF a|m)-algebra, where m is the

non-termination monad

slide-121
SLIDE 121

f-and-m-Algebras for Interleaved IO Effects

  • We can use the initial (ListF a)-and-IO-algebra Listio to give hGetContents

a type that makes its interleaving of data and effects explicit hGetContents :: Handle → Listio

slide-122
SLIDE 122

f-and-m-Algebras for Interleaved IO Effects

  • We can use the initial (ListF a)-and-IO-algebra Listio to give hGetContents

a type that makes its interleaving of data and effects explicit hGetContents :: Handle → Listio

  • We can implement hGetContents using Haskell’s standard primitives

for performing IO on handles hGetContents h = Listio (do isEOF ← hIsEOF h if isEOF then returnio Nilio else do c ← hGetChar h returnio (Consio c (hGetContents h)))

slide-123
SLIDE 123

f-and-m-Algebras for Interleaved IO Effects

  • We can use the initial (ListF a)-and-IO-algebra Listio to give hGetContents

a type that makes its interleaving of data and effects explicit hGetContents :: Handle → Listio

  • We can implement hGetContents using Haskell’s standard primitives

for performing IO on handles hGetContents h = Listio (do isEOF ← hIsEOF h if isEOF then returnio Nilio else do c ← hGetChar h returnio (Consio c (hGetContents h)))

  • Now IO errors are reported within the scope of IO actions, and we

have access to the IO monad to explicitly close the file

slide-124
SLIDE 124

Iteratees

  • Iteratees interleave reading from some input with effects from some

monad, eventually yielding some output data Reader ′ m a b newtype Reader m a b = = Input (Maybe a → Reader m a b) | Yield b Reader (m (Reader ′ m a b))

slide-125
SLIDE 125

Iteratees

  • Iteratees interleave reading from some input with effects from some

monad, eventually yielding some output data Reader ′ m a b newtype Reader m a b = = Input (Maybe a → Reader m a b) | Yield b Reader (m (Reader ′ m a b))

  • A value of type Reader m a b is some effect described by the monad

m, yielding either a result of type b or a request for input of type a

slide-126
SLIDE 126

Iteratees

  • Iteratees interleave reading from some input with effects from some

monad, eventually yielding some output data Reader ′ m a b newtype Reader m a b = = Input (Maybe a → Reader m a b) | Yield b Reader (m (Reader ′ m a b))

  • A value of type Reader m a b is some effect described by the monad

m, yielding either a result of type b or a request for input of type a

  • The Reader m a b type is the initial f-and-m-algebra, where f is

data ReaderF m a b x = Input (Maybe a → x) | Yield b

slide-127
SLIDE 127

Iteratees

  • Iteratees interleave reading from some input with effects from some

monad, eventually yielding some output data Reader ′ m a b newtype Reader m a b = = Input (Maybe a → Reader m a b) | Yield b Reader (m (Reader ′ m a b))

  • A value of type Reader m a b is some effect described by the monad

m, yielding either a result of type b or a request for input of type a

  • The Reader m a b type is the initial f-and-m-algebra, where f is

data ReaderF m a b x = Input (Maybe a → x) | Yield b

  • We can use Proof Principle 2 to reason about programs involving

iteratees, e.g., to prove that Reader m a b is a monad whenever m is

slide-128
SLIDE 128

Pipes

  • The central definition of the pipes library is

data Proxy a′ a b′ b m r = Request a′ (a → Proxy a′ a b′ b m r) | Respond b (b′ → Proxy a′ a b′ b m r) | M m (Proxy a′ a b′ b m r)) | Pure r

slide-129
SLIDE 129

Pipes

  • The central definition of the pipes library is

data Proxy a′ a b′ b m r = Request a′ (a → Proxy a′ a b′ b m r) | Respond b (b′ → Proxy a′ a b′ b m r) | M m (Proxy a′ a b′ b m r)) | Pure r

  • A value of type Proxy a′ a b′ b m r is a tree of requests of type a′ reading

values of type a, and responses of type b reading values of type b′, interleaved with effects described by m, and yielding values of type r

slide-130
SLIDE 130

Pipes

  • The central definition of the pipes library is

data Proxy a′ a b′ b m r = Request a′ (a → Proxy a′ a b′ b m r) | Respond b (b′ → Proxy a′ a b′ b m r) | M m (Proxy a′ a b′ b m r)) | Pure r

  • A value of type Proxy a′ a b′ b m r is a tree of requests of type a′ reading

values of type a, and responses of type b reading values of type b′, interleaved with effects described by m, and yielding values of type r

  • So the Proxy type adds the possibility of bidirectional requests and

responses to the Reader type

slide-131
SLIDE 131

Pipes

  • The central definition of the pipes library is

data Proxy a′ a b′ b m r = Request a′ (a → Proxy a′ a b′ b m r) | Respond b (b′ → Proxy a′ a b′ b m r) | M m (Proxy a′ a b′ b m r)) | Pure r

  • A value of type Proxy a′ a b′ b m r is a tree of requests of type a′ reading

values of type a, and responses of type b reading values of type b′, interleaved with effects described by m, and yielding values of type r

  • So the Proxy type adds the possibility of bidirectional requests and

responses to the Reader type

  • Proxy types are another instance of data interleaved with effects so we

can use Proof Principle 2 to reason about programs involving them

slide-132
SLIDE 132

Conclusions

  • f-algebras are at the wrong level of abstraction for reasoning about

data interleaved with effects

slide-133
SLIDE 133

Conclusions

  • f-algebras are at the wrong level of abstraction for reasoning about

data interleaved with effects

  • Filinski and Støvring’s f-and-m-algebras generalize to categories other

than CPO

slide-134
SLIDE 134

Conclusions

  • f-algebras are at the wrong level of abstraction for reasoning about

data interleaved with effects

  • Filinski and Støvring’s f-and-m-algebras generalize to categories other

than CPO

  • Initial f-and-m-algebras are the effectful analogue of initial f-algebras
slide-135
SLIDE 135

Conclusions

  • f-algebras are at the wrong level of abstraction for reasoning about

data interleaved with effects

  • Filinski and Støvring’s f-and-m-algebras generalize to categories other

than CPO

  • Initial f-and-m-algebras are the effectful analogue of initial f-algebras
  • Initial f-and-m-algebras separate pure and effectful concerns, and thus

let us transfer definitional and proof principles from pure to effectful settings and capture implicit interleaving of effects with data in types

slide-136
SLIDE 136

Conclusions

  • f-algebras are at the wrong level of abstraction for reasoning about

data interleaved with effects

  • Filinski and Støvring’s f-and-m-algebras generalize to categories other

than CPO

  • Initial f-and-m-algebras are the effectful analogue of initial f-algebras
  • Initial f-and-m-algebras separate pure and effectful concerns, and thus

let us transfer definitional and proof principles from pure to effectful settings and capture implicit interleaving of effects with data in types

  • Other effectful data types (iteratees, pipes, etc.) can also be expressed

as initial f-and-m-algebras, making PP2 available for them

slide-137
SLIDE 137

Thank You!

slide-138
SLIDE 138

Example — An Eilenberg-Moore Algebra for Errors

  • An ErrorM -Eilenberg-Moore-algebra with carrier IO a is given by

l :: ErrorM (IO a) → IO a l (Ok ioa) = ioa l (Error msg) = throw (ErrorCall msg)

  • The algebra l propagates normal IO actions, and interprets errors

using the exception throwing facilities of the Haskell IO monad

  • The function throw and the constructor ErrorCall are part of the stan-

dard Control.Exception module

slide-139
SLIDE 139

From Initial (f ◦ m)-Algebras to Initial f-and-m-Algebras

Theorem: Let (f, fmapf) be a functor, and (m, fmapm, returnm, joinm) be a monad. If we have an initial (f ◦ m)-algebra (µ(f ◦ m), in), then m (µ(f ◦ m)) is the carrier of an initial f-and-m-algebra The proof of this theorems gives us a way to implement f-and-m-algebras