-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathExamples.purs
155 lines (109 loc) · 3.47 KB
/
Examples.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
module Test.Examples where
import Prelude
import Data.Tuple (Tuple(..))
import Effect (Effect)
import Effect.Console as Console
import Run (EFFECT, Run, Step(..), interpret, liftEffect, match, on, runAccumPure, runBaseEffect, runCont, send)
import Run as Run
import Type.Proxy (Proxy(..))
import Type.Row (type (+))
data TalkF a
= Speak String a
| Listen (String -> a)
derive instance functorTalkF :: Functor TalkF
type TALK r = (talk :: TalkF | r)
_talk = Proxy :: Proxy "talk"
speak :: forall r. String -> Run (TALK + r) Unit
speak str = Run.lift _talk (Speak str unit)
listen :: forall r. Run (TALK + r) String
listen = Run.lift _talk (Listen identity)
handleTalk :: forall r. TalkF ~> Run (EFFECT + r)
handleTalk = case _ of
Speak str next -> do
liftEffect $ Console.log str
pure next
Listen reply -> do
pure (reply "I am Groot")
runTalk
:: forall r
. Run (EFFECT + TALK + r)
~> Run (EFFECT + r)
runTalk = interpret (on _talk handleTalk send)
---
type IsThereMore = Boolean
type Bill = Int
data Food = Pizza | Chizburger
data DinnerF a
= Eat Food (IsThereMore -> a)
| CheckPlease (Bill -> a)
derive instance functorDinnerF :: Functor DinnerF
type DINNER r = (dinner :: DinnerF | r)
_dinner = Proxy :: Proxy "dinner"
eat :: forall r. Food -> Run (DINNER + r) IsThereMore
eat food = Run.lift _dinner (Eat food identity)
checkPlease :: forall r. Run (DINNER + r) Bill
checkPlease = Run.lift _dinner (CheckPlease identity)
type Tally = { stock :: Int, bill :: Bill }
handleDinner :: forall a. Tally -> DinnerF a -> Tuple Tally a
handleDinner tally = case _ of
Eat _ reply
| tally.stock > 0 ->
let
tally' = { stock: tally.stock - 1, bill: tally.bill + 1 }
in
Tuple tally' (reply true)
| otherwise ->
Tuple tally (reply false)
CheckPlease reply ->
Tuple tally (reply tally.bill)
runDinnerPure :: forall r a. Tally -> Run (DINNER + r) a -> Run r (Tuple Bill a)
runDinnerPure = runAccumPure
(\tally -> on _dinner (Loop <<< handleDinner tally) Done)
(\tally a -> Tuple tally.bill a)
---
type LovelyEvening r = (TALK + DINNER + r)
dinnerTime :: forall r. Run (LovelyEvening r) Unit
dinnerTime = do
speak "I'm famished!"
isThereMore <- eat Pizza
if isThereMore then dinnerTime
else do
bill <- checkPlease
speak "Outrageous!"
program2 :: forall r. Run (EFFECT + DINNER + r) Unit
program2 = dinnerTime # runTalk
program3 :: forall r. Run (EFFECT + r) (Tuple Bill Unit)
program3 = program2 # runDinnerPure { stock: 10, bill: 0 }
main :: Effect (Tuple Bill Unit)
main = runBaseEffect program3
---
foreign import setTimeout :: Int -> Effect Unit -> Effect Unit
---
data LogF a = Log String a
derive instance functorLogF :: Functor LogF
type LOG r = (log :: LogF | r)
_log = Proxy :: Proxy "log"
log :: forall r. String -> Run (LOG + r) Unit
log str = Run.lift _log (Log str unit)
---
data SleepF a = Sleep Int a
derive instance functorSleepF :: Functor SleepF
type SLEEP r = (sleep :: SleepF | r)
_sleep = Proxy :: Proxy "sleep"
sleep :: forall r. Int -> Run (SLEEP + r) Unit
sleep ms = Run.lift _sleep (Sleep ms unit)
---
programSleep :: forall r. Run (SLEEP + LOG + r) Unit
programSleep = do
log "I guess I'll wait..."
sleep 3000
log "I can't wait any longer!"
mainSleep :: Effect Unit
mainSleep = programSleep # runCont go done
where
go = match
{ log: \(Log str cb) -> Console.log str *> cb
, sleep: \(Sleep ms cb) -> setTimeout ms cb
}
done _ = do
Console.log "Done!"