Effect handler oriented programming Sam Lindley The University of - - PowerPoint PPT Presentation

effect handler oriented programming
SMART_READER_LITE
LIVE PREVIEW

Effect handler oriented programming Sam Lindley The University of - - PowerPoint PPT Presentation

Effect handler oriented programming Sam Lindley The University of Edinburgh and Imperial College London 18th February 2020 Part I Prologue C E K R e l a t i o n a l L i n k s Ma c h i n e L e n s e s Q u e r y


slide-1
SLIDE 1

Effect handler oriented programming

Sam Lindley

The University of Edinburgh and Imperial College London

18th February 2020

slide-2
SLIDE 2

Part I Prologue

slide-3
SLIDE 3

L i n k s

http://www.links-lang.org

Database Integration Concurrency & Distribution Effect Handlers WeB Development Interactive Programming

L i n k i n g t h e

  • r

y t

  • p

r a c t i c e f

  • r

t h e w e b

Q u e r y S h r e d d i n g L a n g u a g e

  • I

n t e g r a t e d Q u e r y P r

  • v

e n a n c e R e l a t i

  • n

a l L e n s e s T y p e d H T ML + a n t i q u

  • t

e s F

  • r

ml e t s Mo d e l

  • V

i e w

  • U

p d a t e C P S T r a n s l a t i

  • n

( C l i e n t ) R

  • w
  • b

a s e d E fg e c t s C E K Ma c h i n e ( S e r v e r ) R P C C a l c u l u s S e s s i

  • n

E x c e p t i

  • n

s

D i s t r i b u t e d S e s s i

  • n

T y p e s

T r y L i n k s

N

  • t

e b

  • k

P r

  • g

r a mmi n g

Wi t h t h a n k s t

  • S

i m

  • n

F

  • w

l e r

slide-4
SLIDE 4

Part II Effect handler oriented programming

slide-5
SLIDE 5

Effects

Programs as black boxes (Church-Turing model)?

slide-6
SLIDE 6

Effects

Programs must interact with their environment

slide-7
SLIDE 7

Effects

Programs must interact with their environment Effects are pervasive ◮ input/output user interaction ◮ concurrency web applications ◮ distribution cloud computing ◮ exceptions fault tolerance ◮ choice backtracking search

slide-8
SLIDE 8

Effects

Programs must interact with their environment Effects are pervasive ◮ input/output user interaction ◮ concurrency web applications ◮ distribution cloud computing ◮ exceptions fault tolerance ◮ choice backtracking search Typically ad hoc and hard-wired

slide-9
SLIDE 9

Effect handlers

Deep theory

Gordon Plotkin Matija Pretnar Handlers of algebraic effects, ESOP 2009

slide-10
SLIDE 10

Effect handlers

Deep theory

Gordon Plotkin Matija Pretnar Handlers of algebraic effects, ESOP 2009 Composable and user-defined interpretation of effects in general

slide-11
SLIDE 11

Effect handlers

Deep theory

Gordon Plotkin Matija Pretnar Handlers of algebraic effects, ESOP 2009 Composable and user-defined interpretation of effects in general Give programmer direct access to environment (c.f. resumable exceptions, monads, delimited control)

slide-12
SLIDE 12

Effect handlers

Deep theory

Gordon Plotkin Matija Pretnar Handlers of algebraic effects, ESOP 2009 Composable and user-defined interpretation of effects in general Give programmer direct access to environment (c.f. resumable exceptions, monads, delimited control) Growing industrial interest React JavaScript UI library (used by > 1 million websites) Pyro Probabilistic programming language (statistical inference) Semantic Code analysis library (> 4.5 million Python repositories)

slide-13
SLIDE 13

Example 1: choice and failure

Effect signature

{choose : 1 ⇒ Bool, fail : a.1 ⇒ a}

slide-14
SLIDE 14

Example 1: choice and failure

Effect signature

{choose : 1 ⇒ Bool, fail : a.1 ⇒ a}

Drunk coin tossing

toss () = if choose () then Heads else Tails drunkToss () = if choose () then if choose () then Heads else Tails else fail () drunkTosses n = if n = 0 then [] else drunkToss () :: drunkTosses (n − 1)

slide-15
SLIDE 15

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing

slide-16
SLIDE 16

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing

slide-17
SLIDE 17

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True

slide-18
SLIDE 18

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True handle 42 with trueChoice = ⇒ 42 handle toss () with trueChoice = ⇒ Heads

slide-19
SLIDE 19

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True handle 42 with trueChoice = ⇒ 42 handle toss () with trueChoice = ⇒ Heads allChoices = — non-linear handler return x → [x] choose () → r → r True + + r False

slide-20
SLIDE 20

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True handle 42 with trueChoice = ⇒ 42 handle toss () with trueChoice = ⇒ Heads allChoices = — non-linear handler return x → [x] choose () → r → r True + + r False handle 42 with allChoices = ⇒ [42] handle toss () with allChoices = ⇒ [Heads, Tails]

slide-21
SLIDE 21

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True handle 42 with trueChoice = ⇒ 42 handle toss () with trueChoice = ⇒ Heads allChoices = — non-linear handler return x → [x] choose () → r → r True + + r False handle 42 with allChoices = ⇒ [42] handle toss () with allChoices = ⇒ [Heads, Tails] handle (handle drunkTosses 2 with maybeFail) with allChoices = ⇒

slide-22
SLIDE 22

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True handle 42 with trueChoice = ⇒ 42 handle toss () with trueChoice = ⇒ Heads allChoices = — non-linear handler return x → [x] choose () → r → r True + + r False handle 42 with allChoices = ⇒ [42] handle toss () with allChoices = ⇒ [Heads, Tails] handle (handle drunkTosses 2 with maybeFail) with allChoices = ⇒ [Just [Heads, Heads], Just [Heads, Tails], Nothing, Just [Tails, Heads], Just [Tails, Tails], Nothing, Nothing]

slide-23
SLIDE 23

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True handle 42 with trueChoice = ⇒ 42 handle toss () with trueChoice = ⇒ Heads allChoices = — non-linear handler return x → [x] choose () → r → r True + + r False handle 42 with allChoices = ⇒ [42] handle toss () with allChoices = ⇒ [Heads, Tails] handle (handle drunkTosses 2 with maybeFail) with allChoices = ⇒ [Just [Heads, Heads], Just [Heads, Tails], Nothing, Just [Tails, Heads], Just [Tails, Tails], Nothing, Nothing] handle (handle drunkTosses 2 with allChoices) with maybeFail = ⇒

slide-24
SLIDE 24

Example 1: choice and failure

Handlers

maybeFail = — exception handler return x → Just x fail () → Nothing handle 42 with maybeFail = ⇒ Just 42 handle fail () with maybeFail = ⇒ Nothing trueChoice = — linear handler return x → x choose () → r → r True handle 42 with trueChoice = ⇒ 42 handle toss () with trueChoice = ⇒ Heads allChoices = — non-linear handler return x → [x] choose () → r → r True + + r False handle 42 with allChoices = ⇒ [42] handle toss () with allChoices = ⇒ [Heads, Tails] handle (handle drunkTosses 2 with maybeFail) with allChoices = ⇒ [Just [Heads, Heads], Just [Heads, Tails], Nothing, Just [Tails, Heads], Just [Tails, Tails], Nothing, Nothing] handle (handle drunkTosses 2 with allChoices) with maybeFail = ⇒ Nothing

slide-25
SLIDE 25

Small-step operational semantics for (deep) effect handlers

Reduction rules

let x = V in N N[V /x] handle V with H Nret[V /x] handle E[op V ] with H Nop[V /p, (λx.handle E[x] with H)/r],

  • p # E

where H = return x → Nret

  • p1 p → r → Nop1

· · ·

  • pk p → r → Nopk

Evaluation contexts

E ::= [ ] | let x = E in N | handle E with H

slide-26
SLIDE 26

Example 2: cooperative concurrency (static)

Effect signature

{yield : 1 ⇒ 1}

slide-27
SLIDE 27

Example 2: cooperative concurrency (static)

Effect signature

{yield : 1 ⇒ 1}

Two cooperative lightweight threads

tA () = print (“A1 ”); yield (); print (“A2 ”) tB () = print (“B1 ”); yield (); print (“B2 ”)

slide-28
SLIDE 28

Example 2: cooperative concurrency (static)

Effect signature

{yield : 1 ⇒ 1}

Two cooperative lightweight threads

tA () = print (“A1 ”); yield (); print (“A2 ”) tB () = print (“B1 ”); yield (); print (“B2 ”)

Handler

— parameterised handler coop ([]) = return () → () yield () → r′ → r′ [] () coop (r :: rs) = return () → r rs () yield () → r′ → r (rs + + [r′]) ()

slide-29
SLIDE 29

Example 2: cooperative concurrency (static)

Effect signature

{yield : 1 ⇒ 1}

Two cooperative lightweight threads

tA () = print (“A1 ”); yield (); print (“A2 ”) tB () = print (“B1 ”); yield (); print (“B2 ”)

Handler

— parameterised handler coop ([]) = return () → () yield () → r′ → r′ [] () coop (r :: rs) = return () → r rs () yield () → r′ → r (rs + + [r′]) ()

Helpers

coopWith t rs () = handle t () with coop rs cooperate ts = coopWith id (map coopWith ts) ()

slide-30
SLIDE 30

Example 2: cooperative concurrency (static)

Effect signature

{yield : 1 ⇒ 1}

Two cooperative lightweight threads

tA () = print (“A1 ”); yield (); print (“A2 ”) tB () = print (“B1 ”); yield (); print (“B2 ”)

Handler

— parameterised handler coop ([]) = return () → () yield () → r′ → r′ [] () coop (r :: rs) = return () → r rs () yield () → r′ → r (rs + + [r′]) ()

Helpers

coopWith t rs () = handle t () with coop rs cooperate ts = coopWith id (map coopWith ts) () cooperate [tA, tB] = ⇒ () A1 B1 A2 B2

slide-31
SLIDE 31

Small-step operational semantics for parameterised effect handlers

Reduction rules

let x = V in N N[V /x] handle V with H W Nret[V /x, W /h] handle E[op V ] with H W Nop[V /p, W /h, (λh x.handle E[x] with H h)/r],

  • p # E

where H h = return x → Nret

  • p1 p → r → Nop1

· · ·

  • pk p → r → Nopk

Evaluation contexts

E ::= [ ] | let x = E in N | handle E with H W

slide-32
SLIDE 32

Small-step operational semantics for parameterised effect handlers

Reduction rules

let x = V in N N[V /x] handle V with H W Nret[V /x, W /h] handle E[op V ] with H W Nop[V /p, W /h, (λh x.handle E[x] with H h)/r],

  • p # E

where H h = return x → Nret

  • p1 p → r → Nop1

· · ·

  • pk p → r → Nopk

Evaluation contexts

E ::= [ ] | let x = E in N | handle E with H W Exercise: express parameterised handlers as non-parameterised handlers

slide-33
SLIDE 33

Example 3: cooperative concurrency (dynamic)

Effect signature

— recursive effect signature Co = {yield : 1 ⇒ 1, fork : (1 → [Co]1) ⇒ 1}

slide-34
SLIDE 34

Example 3: cooperative concurrency (dynamic)

Effect signature

— recursive effect signature Co = {yield : 1 ⇒ 1, fork : (1 → [Co]1) ⇒ 1}

A single cooperative program

main () = print “M1 ”; fork (λ().print “A1 ”; yield (); print “A2 ”); print “M2 ”; fork (λ().print “B1 ”; yield (); print “B2 ”); print “M3 ”

slide-35
SLIDE 35

Example 3: cooperative concurrency (dynamic)

Effect signature

— recursive effect signature Co = {yield : 1 ⇒ 1, fork : (1 → [Co]1) ⇒ 1}

A single cooperative program

main () = print “M1 ”; fork (λ().print “A1 ”; yield (); print “A2 ”); print “M2 ”; fork (λ().print “B1 ”; yield (); print “B2 ”); print “M3 ”

Parameterised handler and helpers

coop ([]) = return () → () yield () → r′ → r′ [] () fork t → r′ → coopWith t [r′] () coop (r :: rs) = return () → r rs () yield () → r′ → r (rs + + [r′]) () fork t → r′ → coopWith t (r :: rs + + [r′]) () coopWith t rs () = handle t () with coop rs cooperate ts = coopWith id (map coopWith ts) ()

slide-36
SLIDE 36

Example 3: cooperative concurrency (dynamic)

Effect signature

— recursive effect signature Co = {yield : 1 ⇒ 1, fork : (1 → [Co]1) ⇒ 1}

A single cooperative program

main () = print “M1 ”; fork (λ().print “A1 ”; yield (); print “A2 ”); print “M2 ”; fork (λ().print “B1 ”; yield (); print “B2 ”); print “M3 ”

Parameterised handler and helpers

coop ([]) = return () → () yield () → r′ → r′ [] () fork t → r′ → coopWith t [r′] () coop (r :: rs) = return () → r rs () yield () → r′ → r (rs + + [r′]) () fork t → r′ → coopWith t (r :: rs + + [r′]) () coopWith t rs () = handle t () with coop rs cooperate ts = coopWith id (map coopWith ts) () cooperate [main] = ⇒ () M1 A1 M2 B1 A2 M3 B2

slide-37
SLIDE 37

Example 3: cooperative concurrency (dynamic)

Effect signature

— recursive effect signature Co = {yield : 1 ⇒ 1, fork : (1 → [Co]1) ⇒ 1}

A single cooperative program

main () = print “M1 ”; fork (λ().print “A1 ”; yield (); print “A2 ”); print “M2 ”; fork (λ().print “B1 ”; yield (); print “B2 ”); print “M3 ”

Parameterised handler and helpers

coop ([]) = return () → () yield () → r′ → r′ [] () fork t → r′ → r′ [coopWith t] () coop (r :: rs) = return () → r rs () yield () → r′ → r (rs + + [r′]) () fork t → r′ → r′ (r :: rs + + [coopWith t]) () coopWith t rs () = handle t () with coop rs cooperate ts = coopWith id (map coopWith ts) ()

slide-38
SLIDE 38

Example 3: cooperative concurrency (dynamic)

Effect signature

— recursive effect signature Co = {yield : 1 ⇒ 1, fork : (1 → [Co]1) ⇒ 1}

A single cooperative program

main () = print “M1 ”; fork (λ().print “A1 ”; yield (); print “A2 ”); print “M2 ”; fork (λ().print “B1 ”; yield (); print “B2 ”); print “M3 ”

Parameterised handler and helpers

coop ([]) = return () → () yield () → r′ → r′ [] () fork t → r′ → r′ [coopWith t] () coop (r :: rs) = return () → r rs () yield () → r′ → r (rs + + [r′]) () fork t → r′ → r′ (r :: rs + + [coopWith t]) () coopWith t rs () = handle t () with coop rs cooperate ts = coopWith id (map coopWith ts) () cooperate [main] = ⇒ () M1 M2 M3 A1 B1 A2 B2

slide-39
SLIDE 39

Example 4: pipes

Effect signatures

Sender = {send : Nat ⇒ 1} Receiver = {receive : 1 ⇒ Nat}

slide-40
SLIDE 40

Example 4: pipes

Effect signatures

Sender = {send : Nat ⇒ 1} Receiver = {receive : 1 ⇒ Nat}

A producer and a consumer

nats n = send n; nats (n + 1) grabANat () = receive ()

slide-41
SLIDE 41

Example 4: pipes

Effect signatures

Sender = {send : Nat ⇒ 1} Receiver = {receive : 1 ⇒ Nat}

A producer and a consumer

nats n = send n; nats (n + 1) grabANat () = receive ()

Pipes and copipes as shallow handlers

pipe p c = handle† c () with return x → x receive () → r → copipe r p copipe c p = handle† p () with return x → x send n → r → pipe r (λ().c n)

slide-42
SLIDE 42

Example 4: pipes

Effect signatures

Sender = {send : Nat ⇒ 1} Receiver = {receive : 1 ⇒ Nat}

A producer and a consumer

nats n = send n; nats (n + 1) grabANat () = receive ()

Pipes and copipes as shallow handlers

pipe p c = handle† c () with return x → x receive () → r → copipe r p copipe c p = handle† p () with return x → x send n → r → pipe r (λ().c n) pipe (λ().nats 0) grabANat + copipe (λx.x) (λ().nats 0) + pipe (λ().nats 1) (λ().0) + 0

slide-43
SLIDE 43

Example 4: pipes

Effect signatures

Sender = {send : Nat ⇒ 1} Receiver = {receive : 1 ⇒ Nat}

A producer and a consumer

nats n = send n; nats (n + 1) grabANat () = receive ()

Pipes and copipes as shallow handlers

pipe p c = handle† c () with return x → x receive () → r → copipe r p copipe c p = handle† p () with return x → x send n → r → pipe r (λ().c n) pipe (λ().nats 0) grabANat + copipe (λx.x) (λ().nats 0) + pipe (λ().nats 1) (λ().0) + 0 Exercise: implement pipes using deep handlers

slide-44
SLIDE 44

Small-step operational semantics for shallow effect handlers

Reduction rules

let x = V in N N[V /x] handle† V with H Nret[V /x] handle† E[op V ] with H Nop[V /p, (λx.E[x])/r],

  • p # E

where H = return x → Nret

  • p1 p → r → Nop1

· · ·

  • pk p → r → Nopk

Evaluation contexts

E ::= [ ] | let x = E in N | handle† E with H

slide-45
SLIDE 45

Small-step operational semantics for shallow effect handlers

Reduction rules

let x = V in N N[V /x] handle† V with H Nret[V /x] handle† E[op V ] with H Nop[V /p, (λx.E[x])/r],

  • p # E

where H = return x → Nret

  • p1 p → r → Nop1

· · ·

  • pk p → r → Nopk

Evaluation contexts

E ::= [ ] | let x = E in N | handle† E with H Exercise: express shallow handlers as deep handlers

slide-46
SLIDE 46

Built-in effects

Console I/O

Console = {inch : 1 ⇒ char

  • uch : char ⇒ 1}

print s = map (λc.ouch c) s; ()

State

State = {new : a. a ⇒ Ref a, write : a. (Ref a × a) ⇒ 1, read : a. Ref a ⇒ a}

slide-47
SLIDE 47

Example 5: actors

Process ids

Pid a = Ref (List a)

Effect signature

Actor a = {self : 1 ⇒ Pid a, spawn : b. (1 → [Actor b]1) ⇒ Pid b, send : b. (b × Pid b) ⇒ 1, recv : 1 ⇒ a}

slide-48
SLIDE 48

Example 5: actors

Process ids

Pid a = Ref (List a)

Effect signature

Actor a = {self : 1 ⇒ Pid a, spawn : b. (1 → [Actor b]1) ⇒ Pid b, send : b. (b × Pid b) ⇒ 1, recv : 1 ⇒ a}

An actor chain

spawnMany p 0 = send (“ping!”, p) spawnMany p n = spawnMany (spawn (λ().let s = recv () in print “.”; send (s, p))) (n − 1) chain n = spawnMany (self ()) n; let s = recv () in print s

slide-49
SLIDE 49

Example 5: actors

Actors via cooperative concurrency

act mine = return () → () self () → r → r mine mine spawn you → r → let yours = new [] in fork (λ().act yours (you ())); r mine yours send (m, yours) → r → let ms = read yours in write (yours, ms + + [m]); r mine () recv () → r → case read mine of [] → yield (); r mine (recv ()) (m :: ms) → write (mine, ms); r mine m

slide-50
SLIDE 50

Example 5: actors

Actors via cooperative concurrency

act mine = return () → () self () → r → r mine mine spawn you → r → let yours = new [] in fork (λ().act yours (you ())); r mine yours send (m, yours) → r → let ms = read yours in write (yours, ms + + [m]); r mine () recv () → r → case read mine of [] → yield (); r mine (recv ()) (m :: ms) → write (mine, ms); r mine m cooperate [handle chain 64 with act (new [])] = ⇒ () ................................................................ping!

slide-51
SLIDE 51

Effect handler oriented programming languages

Eff https://www.eff-lang.org/ Frank https://github.com/frank-lang/frank Helium https://bitbucket.org/pl-uwr/helium Links https://www.links-lang.org/ Koka https://github.com/koka-lang/koka Multicore OCaml https://github.com/ocamllabs/ocaml-multicore/wiki

slide-52
SLIDE 52

Effect handlers — some of my contributions

Handlers in action (ICFP 2013) with Kammar and Oury Effect handlers in Links (TyDe 2016 / JFP 2020) with Hillerstr¨

  • m

Frank programming language (POPL 2017 / JFP 2020) with Convent, McBride, and McLaughlin Expressive power of effect handlers (ICFP 2017 / JFP 2019) with Forster, Kammar, and Pretnar Continuation-passing style for effect handlers (FSCD 2017 / JFP 2020) with Atkey, Hillerstr¨

  • m, and Sivaramakrishnan

Shallow effect handlers (APLAS 2018 / JFP 2020) with Hillerstr¨

  • m

Linear effect handlers for session exceptions (POPL 2019) with Decova, Fowler, and Morris

slide-53
SLIDE 53

Scalability challenges

Modularity — effect typing

◮ Effect encapsulation ◮ Linearity ◮ Generativity ◮ Indexed effects ◮ Equations

Efficiency — compilation techniques

◮ Segmented stacks (Multicore OCaml / C library) ◮ Continuation Passing Style (JavaScript backends) ◮ Fusion (Haskell libraries / Eff) ◮ Staging (Scala Effekt library)

slide-54
SLIDE 54

New directions

Effect handlers for Wasm add effect handlers once and for all — avoid pitfalls of JavaScript Asynchronous effects pre-emptive concurrency; reactive programming Gradually typed effect handlers transition mainstream languages towards effect typing Hardware capabilities as dynamic effects safe effect handlers in C? efficient implementation? Lexically scoped effect handlers improved hygiene? improved performance? improved reasoning?

slide-55
SLIDE 55

Resources

Jeremy Yallop’s effects bibliography https://github.com/yallop/effects-bibliography Matija Pretnar’s tutorial “An introduction to algebraic effects and handlers”, MFPS 2015 Andrej Bauer’s tutorial “What is algebraic about algebraic effects and handlers?”, Dagstuhl and OPLSS 2018

slide-56
SLIDE 56

Part III Bonus slides

slide-57
SLIDE 57

Example 6: effect pollution

Effect signatures

Receiver = {receive : 1 ⇒ Nat} Failure = {fail : a.1 ⇒ a}

slide-58
SLIDE 58

Example 6: effect pollution

Effect signatures

Receiver = {receive : 1 ⇒ Nat} Failure = {fail : a.1 ⇒ a}

Handlers

receives ([]) = return x → x receive () → r → fail () receives (n :: ns) = return x → x receive () → r → r ns n maybeFail = return x → Just x fail () → r → Nothing

slide-59
SLIDE 59

Example 6: effect pollution

Effect signatures

Receiver = {receive : 1 ⇒ Nat} Failure = {fail : a.1 ⇒ a}

Handlers

receives ([]) = return x → x receive () → r → fail () receives (n :: ns) = return x → x receive () → r → r ns n maybeFail = return x → Just x fail () → r → Nothing bad ns t = handle (handle t () with receives ns) with maybeFail

slide-60
SLIDE 60

Example 6: effect pollution

Effect signatures

Receiver = {receive : 1 ⇒ Nat} Failure = {fail : a.1 ⇒ a}

Handlers

receives ([]) = return x → x receive () → r → fail () receives (n :: ns) = return x → x receive () → r → r ns n maybeFail = return x → Just x fail () → r → Nothing bad ns t = handle (handle t () with receives ns) with maybeFail bad [1, 2] (λ().receive () + fail ()) = ⇒ Nothing

slide-61
SLIDE 61

Example 7: counting

Predicates as higher order functions

Pred = (Nat → Bool) → Bool

Signature of a counting function

count : ((Nat → Bool) → Bool) → Nat

Exclusive or

count (λv.if v 0 then not (v 1) else v 1) = 2

slide-62
SLIDE 62

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-63
SLIDE 63

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-64
SLIDE 64

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-65
SLIDE 65

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-66
SLIDE 66

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-67
SLIDE 67

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-68
SLIDE 68

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-69
SLIDE 69

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-70
SLIDE 70

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-71
SLIDE 71

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-72
SLIDE 72

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-73
SLIDE 73

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-74
SLIDE 74

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-75
SLIDE 75

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False

slide-76
SLIDE 76

Example 7: counting

Counting with a choice handler

count : ((Nat → Bool) → Bool) → Nat count = λp.handle p (λ .choose ()) with return x → if x then 1 else 0 choose () → r → r True + r False

Exclusive or

count (λv.if v 0 then not (v 1) else v 1)

?0 ?1 !False !True ?1 !True !False