Last time: monads (etc.) = > > 1/ 40 This time: - - PowerPoint PPT Presentation

last time monads etc
SMART_READER_LITE
LIVE PREVIEW

Last time: monads (etc.) = > > 1/ 40 This time: - - PowerPoint PPT Presentation

Last time: monads (etc.) = > > 1/ 40 This time: applicatives (etc.) 2/ 40 Example effects Effects unavailable in OCaml Effects available in OCaml non-determinism (higher-order) state amb f g h r := f; !r () first-class


slide-1
SLIDE 1

Last time: monads (etc.) > > =

1/ 40

slide-2
SLIDE 2

This time: applicatives (etc.) ⊗

2/ 40

slide-3
SLIDE 3

Example effects

Effects available in OCaml (higher-order) state r := f; !r () exceptions raise Not found I/O of various sorts input byte stdin concurrency (interleaving)

  • Gc. finalise

v f non-termination let rec f x = f x Effects unavailable in OCaml non-determinism amb f g h first-class continuations escape x in e polymorphic state r := ”one”; r := 2 checked exceptions int

IOError

− − − − → bool

3/ 40

slide-4
SLIDE 4

Monads, bind and let!

An imperative program

l e t id = ! counter in l e t () = counter := id + 1 in s t r i n g o f i n t id

A monadic program

get > > = fun id → put ( id + 1) > > = fun () → r e t u r n ( s t r i n g o f i n t id )

4/ 40

slide-5
SLIDE 5

Type parameters and instantiation

monads type ’a t let .. in indexed monads type (’e, ’a) t Γ ⊢ M : A ! e parameterised monads type (’ s, ’t, ’a) t {P} C {Q}

5/ 40

slide-6
SLIDE 6

Monadic effect are higher-order

composeE : (a

E

− − → b) → (b

E

− − → c) → (a

E

− − → c) pairE : (a

E

− − → b) → (c

E

− − → d) → (a × c

E

− − → b × d) uncurryE : (a

E

− − → b

E

− − → c) → (a × b

E

− − → c) liftPure : (a → b) → (a

E

− − → b)

6/ 40

slide-7
SLIDE 7

Higher-order effects with monads

v a l uncurryM : ( ’ a → ( ’ b → ’ c t ) t ) → (( ’ a ∗ ’b) → ’ c t ) l e t uncurryM f ( x , y ) = f x > > = fun g → g y

7/ 40

slide-8
SLIDE 8

Applicatives

( let . . . and)

8/ 40

slide-9
SLIDE 9

Allowing only “static” effects

Idea: stop information flowing from one computation into another. Only allow unparameterised computations: 1

E

− − → b We can no longer write functions like this: composeE : (a

E

− − → b) → (b

E

− − → c) → (a

E

− − → c) but some useful functions are still possible: pairEstatic : (1

E

− − → a) → (1

E

− − → b) → (1

E

− − → a × b)

9/ 40

slide-10
SLIDE 10

Applicative programs

An imperative program

l e t x = fresh name () and y = fresh name () in ( x , y )

An applicative program

pure ( fun x y → ( x , y )) ⊗ fresh name ⊗ fresh name

10/ 40

slide-11
SLIDE 11

Applicatives

module type APPLICATIVE = s i g type ’ a t v a l pure : ’ a → ’ a t v a l (⊗) : ( ’ a → ’b) t → ’ a t → ’b t end

11/ 40

slide-12
SLIDE 12

Applicatives

module type APPLICATIVE = s i g type ’ a t v a l pure : ’ a → ’ a t v a l (⊗) : ( ’ a → ’b) t → ’ a t → ’b t end Laws: pure f ⊗ pure v ≡ pure (f v) u ≡ pure id ⊗ u u ⊗ (v ⊗ w) ≡ pure compose ⊗ u ⊗ v ⊗ w v ⊗ pure x ≡ pure (fun f → f x) ⊗ v

11/ 40

slide-13
SLIDE 13

> > = vs ⊗

The type of > > =: ’a t → (’a → ’b t) → ’b t ’a → ’b t: a function that builds a computation (Almost) the type of ⊗: ’a t → (’a → ’b) t → ’b t (’a → ’b) t: a computation that builds a function The actual type of ⊗: (’a → ’b) t → ’a t → ’b t

12/ 40

slide-14
SLIDE 14

Applicative normal forms

pure f ⊗ c1 ⊗ c2 . . . ⊗ cn pure (fun x1 x2 . . . xn → e) ⊗ c1 ⊗ c2 . . . ⊗ cn l e t ! x1 = c1 and ! x2 = c2 . . . and ! xn = cn in e

13/ 40

slide-15
SLIDE 15

Applicative normalisation via the laws

pure f ⊗ (pure g ⊗ fresh name) ⊗ fresh name

14/ 40

slide-16
SLIDE 16

Applicative normalisation via the laws

pure f ⊗ (pure g ⊗ fresh name) ⊗ fresh name ≡ (composition law) (pure compose ⊗ pure f ⊗ pure g ⊗ fresh name) ⊗ fresh name

14/ 40

slide-17
SLIDE 17

Applicative normalisation via the laws

pure f ⊗ (pure g ⊗ fresh name) ⊗ fresh name ≡ (composition law) (pure compose ⊗ pure f ⊗ pure g ⊗ fresh name) ⊗ fresh name ≡ (homomorphism law (×2)) pure (compose f g) ⊗ fresh name ⊗ fresh name

14/ 40

slide-18
SLIDE 18

Creating applicatives: every monad is an applicative

module Applicative of monad (M:MONAD) : APPLICATIVE with type ’ a t = ’ a M. t = s t r u c t type ’ a t = ’ a M. t l e t pure = M. r e t u r n l e t (⊗) f p =

  • M. ( f >

> = fun g → p > > = fun q → r e t u r n ( g q )) end

15/ 40

slide-19
SLIDE 19

The state applicative via the state monad

module StateA (S : s i g type t end ) : s i g type s t a t e = S . t i n c l u d e APPLICATIVE v a l get : s t a t e t v a l put : s t a t e → u n i t t v a l runState : ’ a t → i n i t : s t a t e → s t a t e ∗ ’ a end = s t r u c t type s t a t e = S . t i n c l u d e Applicative of monad ( State (S )) l e t ( get , put , runState ) = M. ( get , put , runState ) end

16/ 40

slide-20
SLIDE 20

Creating applicatives: composing applicatives

module Compose (F : APPLICATIVE) (G : APPLICATIVE) : APPLICATIVE with type ’ a t = ’ a G. t F . t = s t r u c t type ’ a t = ’ a G. t F . t l e t pure x = F . pure (G. pure x ) l e t (⊗) f x = F . ( pure G. ( ⊗) ⊗ f ⊗ x ) end

17/ 40

slide-21
SLIDE 21

Creating applicatives: the dual applicative

module D u a l a p p l i c a t i v e (A: APPLICATIVE) : APPLICATIVE with type ’ a t = ’ a A. t = s t r u c t type ’ a t = ’ a A. t l e t pure = A. pure l e t (⊗) f x =

  • A. ( pure

( fun y g → g y ) ⊗ x ⊗ f ) end

18/ 40

slide-22
SLIDE 22

Composed applicatives are law-abiding

pure f ⊗ pure x

19/ 40

slide-23
SLIDE 23

Composed applicatives are law-abiding

pure f ⊗ pure x ≡ (definition of ⊗ and pure) F.pure (⊗G ) ⊗F F.pure (G.pure f) ⊗F F.pure (G.pure x)

19/ 40

slide-24
SLIDE 24

Composed applicatives are law-abiding

pure f ⊗ pure x ≡ (definition of ⊗ and pure) F.pure (⊗G ) ⊗F F.pure (G.pure f) ⊗F F.pure (G.pure x) ≡ (homomorphism law for F (×2)) F.pure (G.pure f ⊗G G.pure x)

19/ 40

slide-25
SLIDE 25

Composed applicatives are law-abiding

pure f ⊗ pure x ≡ (definition of ⊗ and pure) F.pure (⊗G ) ⊗F F.pure (G.pure f) ⊗F F.pure (G.pure x) ≡ (homomorphism law for F (×2)) F.pure (G.pure f ⊗G G.pure x) ≡ (homomorphism law for G) F.pure (G.pure (f x))

19/ 40

slide-26
SLIDE 26

Composed applicatives are law-abiding

pure f ⊗ pure x ≡ (definition of ⊗ and pure) F.pure (⊗G ) ⊗F F.pure (G.pure f) ⊗F F.pure (G.pure x) ≡ (homomorphism law for F (×2)) F.pure (G.pure f ⊗G G.pure x) ≡ (homomorphism law for G) F.pure (G.pure (f x)) ≡ (definition of pure) pure (f x)

19/ 40

slide-27
SLIDE 27

Fresh names, monadically

type ’ a t r e e = Empty : ’ a t r e e | Tree : ’ a t r e e ∗ ’ a ∗ ’ a t r e e → ’ a t r e e module I S t a t e = State ( s t r u c t type t = i n t end ) l e t fresh name : s t r i n g I S t a t e . t = get > > = fun i → put ( i + 1) > > = fun () → r e t u r n ( P r i n t f . s p r i n t f ”x%d” i ) l e t rec l a b e l t r e e : ’ a t r e e → s t r i n g t r e e I S t a t e . t = f u n c t i o n Empty → r e t u r n Empty | Tree ( l , v , r ) → l a b e l t r e e l > > = fun l → fresh name > > = fun name → l a b e l t r e e r > > = fun r → r e t u r n ( Tree ( l , name , r ))

20/ 40

slide-28
SLIDE 28

Naming as a primitive effect

Problem: we cannot write fresh name using the APPLICATIVE interface. l e t fresh name : s t r i n g I S t a t e . t = get > > = fun i → put ( i + 1) > > = fun () → r e t u r n ( P r i n t f . s p r i n t f ”x%d” i ) Solution: introduce it as a primitive effect: module NameA : s i g i n c l u d e APPLICATIVE v a l fresh name : s t r i n g t end = . . .

21/ 40

slide-29
SLIDE 29

Traversing with namer

l e t rec l a b e l t r e e : ’ a t r e e → s t r i n g t r e e NameA. t = f u n c t i o n Empty → pure Empty | Tree ( l , v , r ) → pure ( fun l name r → Tree ( l , name , r )) ⊗ l a b e l t r e e l ⊗ fresh name ⊗ l a b e l t r e e r

22/ 40

slide-30
SLIDE 30

The phantom monoid applicative

module type MONOID = s i g type t v a l zero : t v a l (+ +) : t → t → t end module Phantom monoid (M: MONOID) : APPLICATIVE with type ’ a t = M. t = s t r u c t type ’ a t = M. t l e t pure = M. zero l e t (⊗) = M. ( + +) end

23/ 40

slide-31
SLIDE 31

The phantom monoid applicative

module type MONOID = s i g type t v a l zero : t v a l (+ +) : t → t → t end module Phantom monoid (M: MONOID) : APPLICATIVE with type ’ a t = M. t = s t r u c t type ’ a t = M. t l e t pure = M. zero l e t (⊗) = M. ( + +) end Observation: we cannot implement Phantom monoid as a monad.

23/ 40

slide-32
SLIDE 32

Applicatives vs monads

programs ⊗ > > = implementations > > = ⊗ Some monadic programs are not applicative, e.g. fresh name. Some applicative instances are not monadic, e.g. Phantom monoid.

24/ 40

slide-33
SLIDE 33

Guideline: Postel’s law

Be conservative in what you do, be liberal in what you accept from others.

25/ 40

slide-34
SLIDE 34

Guideline: Postel’s law

Be conservative in what you do, be liberal in what you accept from others.

Conservative in what you do: use applicatives, not monads. (Applicatives give the implementor more freedom.)

25/ 40

slide-35
SLIDE 35

Guideline: Postel’s law

Be conservative in what you do, be liberal in what you accept from others.

Conservative in what you do: use applicatives, not monads. (Applicatives give the implementor more freedom.) Liberal in what you accept: implement monads, not applicatives. (Monads give the user more power.)

25/ 40

slide-36
SLIDE 36

Parameterised and indexed applicatives

module type PARAMETERISED APPLICATIVE = s i g type ( ’ s , ’ t , ’ a ) t v a l u n i t : ’ a → ( ’ s , ’ s , ’ a ) t v a l (⊗) : ( ’ r , ’ s , ’ a → ’b) t → ( ’ s , ’ t , ’ a ) t → ( ’ r , ’ t , ’ b) t end module type INDEXED APPLICATIVE = s i g type ( ’ e , ’ a ) t v a l pure : ’ a → ( ’ e , ’ a ) t v a l (⊗) : ( ’ e , ’ a → ’b) t → ( ’ e , ’ a ) t → ( ’ e , ’ b) t end

26/ 40

slide-37
SLIDE 37

Stack machines

. . . x y

27/ 40

slide-38
SLIDE 38

Recap: stack machine instructions

. . . x y . . . x+y Add . . . y x c . . .

(y,x)[c]

If . . . . . . c PushConst

28/ 40

slide-39
SLIDE 39

Stack machine operations

module type STACK OPS = s i g type ( ’ s , ’ t , ’ a ) t v a l add : ( i n t ∗ ( i n t ∗ ’ s ) , i n t ∗ ’ s , u n i t ) t v a l i f : ( bool ∗ ( ’ a ∗ ( ’ a ∗ ’ s )) , ’ a ∗ ’ s , u n i t ) t v a l push const : ’ a → ( ’ s , ’ a ∗ ’ s , u n i t ) t end

29/ 40

slide-40
SLIDE 40

Stack machines, monadically

module type STACKM = s i g i n c l u d e PARAMETERISED MONAD i n c l u d e STACK OPS with type ( ’ s , ’ t , ’ a ) t := ( ’ s , ’ t , ’ a ) t v a l execute : ( ’ s , ’ t , ’ a ) t → ’ s → ’ t ∗ ’ a end module StackM : STACKM = s t r u c t i n c l u d e PState l e t add = get > > = fun ( x , ( y , s )) → put ( x+y , s ) l e t i f = get ( c , ( t , ( e , s ) ) ) > > = put ( i f c then t e l s e e ) l e t push const k = get > > = fun s → put (k , s ) l e t execute = runState end

30/ 40

slide-41
SLIDE 41

Programming the monadic stack machine

push const 3 > > = fun () → push const 4 > > = fun () → push const 5 > > = fun () → push const true > > = fun () → i f > > = fun () → add > > = fun () → r e t u r n ()

. . .

31/ 40

slide-42
SLIDE 42

Programming the monadic stack machine

push const 3 > > = fun () → push const 4 > > = fun () → push const 5 > > = fun () → push const true > > = fun () → i f > > = fun () → add > > = fun () → r e t u r n ()

. . . . . . 3

31/ 40

slide-43
SLIDE 43

Programming the monadic stack machine

push const 3 > > = fun () → push const 4 > > = fun () → push const 5 > > = fun () → push const true > > = fun () → i f > > = fun () → add > > = fun () → r e t u r n ()

. . . . . . 3 . . . 3 4

31/ 40

slide-44
SLIDE 44

Programming the monadic stack machine

push const 3 > > = fun () → push const 4 > > = fun () → push const 5 > > = fun () → push const true > > = fun () → i f > > = fun () → add > > = fun () → r e t u r n ()

. . . . . . 3 . . . 3 4 . . . 3 4 5

31/ 40

slide-45
SLIDE 45

Programming the monadic stack machine

push const 3 > > = fun () → push const 4 > > = fun () → push const 5 > > = fun () → push const true > > = fun () → i f > > = fun () → add > > = fun () → r e t u r n ()

. . . . . . 3 . . . 3 4 . . . 3 4 5 . . . 3 4 5 T

31/ 40

slide-46
SLIDE 46

Programming the monadic stack machine

push const 3 > > = fun () → push const 4 > > = fun () → push const 5 > > = fun () → push const true > > = fun () → i f > > = fun () → add > > = fun () → r e t u r n ()

. . . . . . 3 . . . 3 4 . . . 3 4 5 . . . 3 4 5 T . . . 3 5

31/ 40

slide-47
SLIDE 47

Programming the monadic stack machine

push const 3 > > = fun () → push const 4 > > = fun () → push const 5 > > = fun () → push const true > > = fun () → i f > > = fun () → add > > = fun () → r e t u r n ()

. . . . . . 3 . . . 3 4 . . . 3 4 5 . . . 3 4 5 T . . . 3 5 . . . 8

31/ 40

slide-48
SLIDE 48

Stack machines, applicatively

module type STACKA = s i g i n c l u d e PARAMETERISED APPLICATIVE i n c l u d e STACK OPS with type ( ’ s , ’ t , ’ a ) t := ( ’ s , ’ t , ’ a ) t v a l execute : ( ’ s , ’ t , ’ a ) t → ’ s → ’ t end module StackA : STACKA = s t r u c t i n c l u d e Applicative of monad ( StackM ) l e t ( add , i f , push const ) = StackM . ( add , i f , push const ) l e t execute m s = f s t ( StackM . execute m s ) end

32/ 40

slide-49
SLIDE 49

Programming the applicative stack machine

pure ( fun () () () () () () → ( ) ) ⊗ push const 3 ⊗ push const 4 ⊗ push const 5 ⊗ push const true ⊗ i f ⊗ add

. . . . . . 3 . . . 3 4 . . . 3 4 5 . . . 3 4 5 T . . . 3 5 . . . 8

33/ 40

slide-50
SLIDE 50

Optimising stack machines

PushConst x :: PushConst y :: PushConst true :: If ⇝ PushConst y

. . . . . . x . . . x y . . . x y b . . . y . . . . . . y

34/ 40

slide-51
SLIDE 51

First-order stack machines, applicatively

l e t rec (++) : type r s t . ( r , s ) i n s t r s → ( s , t ) i n s t r s → ( r , t ) i n s t r s = fun l r → match l with Stop → r | i : : i s → i : : i s ++ r module StackA1 : STACKA = s t r u c t type ( ’ s , ’ t , ’ a ) t = ( ’ s , ’ t ) i n s t r s l e t pure a = Stop l e t (⊗) = (++) l e t add = Add : : Stop l e t i f = I f : : Stop l e t push const v = PushConst v : : Stop l e t execute = (∗ . . . ∗) end

35/ 40

slide-52
SLIDE 52

Optimising stack machines

l e t rec

  • pt

: type s t . ( s , t ) i n s t r s → ( s , t ) i n s t r s = f u n c t i o n [ ] → [ ] | PushConst x : : PushConst y : : PushConst c : : I f : : s →

  • pt

( PushConst ( i f c then y e l s e x ) : : s ) | i : : i s → i : :

  • pt

i s

36/ 40

slide-53
SLIDE 53

First-order stack machines, applicatively

module StackA1 : STACKA = s t r u c t type ( ’ s , ’ t , ’ a ) t = ( ’ s , ’ t ) i n s t r s l e t pure a = Stop l e t (⊗) l r = opt ( l ++ r ) l e t add = Add : : Stop l e t i f = I f : : Stop l e t push const v = PushConst v : : Stop l e t execute = (∗ . . . ∗) end

37/ 40

slide-54
SLIDE 54

Monoids

(;)

38/ 40

slide-55
SLIDE 55

Instantiating applicatives

module type MONOID = s i g type t v a l zero : t v a l (+ +) : t → t → t end M

1

; M

2

; . . . ; M

n

39/ 40

slide-56
SLIDE 56

Summary

monads

l e t ! x1 = M

1 in

l e t ! x2 = M

2 in

. . . l e t ! xn = M

n

in N

applicatives

l e t ! x1 = M

1

and ! x2 = M

2

. . . and ! xn = M

n

in N

monoids

M

1

; M

2

; . . . ; M

n

indexed monads and applicatives Γ ⊢ M : A ! e parameterised monads and applicatives {P} C {Q}

40/ 40