Skip to content

Commit 2d2b1d5

Browse files
committed
Add State.runViaIO that interprets state in IOEff
1 parent 9fcb55c commit 2d2b1d5

2 files changed

Lines changed: 111 additions & 20 deletions

File tree

Effects/IOEff.lean

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Effects.Container
22
import Effects.Prog
3-
import Effects.State
43

54
open scoped Container
65

@@ -51,25 +50,22 @@ end IOEff
5150

5251
section Examples
5352

54-
def logIO {effs : List Effect} [IOEff ∈ effs] (msg : String) : Prog effs Unit :=
53+
def logIO
54+
{effs : List Effect}
55+
[IOEff ∈ effs]
56+
(msg : String)
57+
: Prog effs Unit :=
5558
IOEff.embed (IO.println msg)
5659

57-
def exStateReaderIO : Prog [State Nat, IOEff] Unit := do
58-
let (n : Nat) ← State.get
59-
logIO s!"n={n}"
60-
State.put (n + 1)
61-
logIO "updated state"
62-
63-
def runStateReaderIO : IO Unit :=
64-
exStateReaderIO
65-
|> State.eval 1
66-
|> IOEff.run
60+
def exLog : Prog [IOEff] Unit := do
61+
logIO "a"
62+
logIO "b"
6763

6864
/--
69-
info: n=1
70-
updated state
65+
info: a
66+
b
7167
-/
7268
#guard_msgs in
73-
#eval runStateReaderIO
69+
#eval exLog |> IOEff.run
7470

7571
end Examples

Effects/State.lean

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Effects.Container
22
import Effects.Prog
3+
import Effects.IOEff
34

45
open scoped Container
56

@@ -67,16 +68,110 @@ def run
6768
def eval (s : S) (p : Prog (State S :: effs) α) : Prog effs α :=
6869
Prod.snd <$> run s p
6970

71+
def runViaIO'
72+
[IOEff ∈ effs]
73+
(p : Prog (State S :: effs) α) :
74+
IO.Ref S → Prog effs (S × α) :=
75+
Prog.foldP
76+
(P := fun _ => IO.Ref S → Prog effs (S × α))
77+
(var0 := fun x => fun iost =>
78+
IOEff.embed iost.get |>.bind (fun st => pure (st, x)))
79+
(varS := id)
80+
(op := fun ⟨c, k⟩ =>
81+
match c with
82+
| .inl StateOps.getOp => fun iost =>
83+
IOEff.embed iost.get |>.bind (fun st => k st iost)
84+
| .inl (StateOps.putOp s') => fun iost =>
85+
IOEff.embed (iost.set s') |>.bind (fun _ => k () iost)
86+
| .inr s => fun iost =>
87+
Prog.op ⟨s, fun p => k p iost⟩)
88+
(scp := fun ⟨c, k⟩ =>
89+
match c with
90+
| .inl x => nomatch x
91+
| .inr s => fun iost => Prog.scp ⟨s, fun p => ProgN.varS (k p iost)⟩)
92+
p
93+
94+
def runViaIO
95+
[IOEff ∈ effs]
96+
(s : IO.Ref S)
97+
(p : Prog (State S :: effs) α)
98+
: Prog effs (S × α) :=
99+
runViaIO' p s
100+
101+
def evalViaIO
102+
[IOEff ∈ effs]
103+
(s : IO.Ref S)
104+
(p : Prog (State S :: effs) α)
105+
: Prog effs α :=
106+
Prod.snd <$> runViaIO' p s
107+
70108
end State
71109

72110
section Examples
73111

74112
open State
75113

76-
def tick {effs} [State Nat ∈ effs] : Prog effs Unit := do
77-
let i ← get
78-
put (1 + i)
79-
80-
#guard Prog.run (State.run 0 (do tick; tick)) = (2, ())
114+
def ticks
115+
{effs}
116+
[State Nat ∈ effs]
117+
: Prog effs Nat := do
118+
let n ← get
119+
put (n + 1)
120+
let m ← get
121+
pure (n + 2 * m)
122+
123+
124+
def runTicksPure : Nat × Nat :=
125+
ticks
126+
|> State.run 0
127+
|> Prog.run
128+
129+
#guard runTicksPure = (1, 2)
130+
131+
def runTicksIO : IO (Nat × Nat) := do
132+
let ref ← IO.mkRef 0
133+
ticks
134+
|> State.runViaIO ref
135+
|> IOEff.run
136+
137+
/--
138+
info: (1, 2)
139+
-/
140+
#guard_msgs in
141+
#eval runTicksIO
142+
143+
def twoState
144+
{effs}
145+
[State Bool ∈ effs]
146+
[State Nat ∈ effs]
147+
: Prog effs Unit := do
148+
let b ← get
149+
let n ← get
150+
put (n + 1)
151+
let n ← get
152+
put (b && n > 5)
153+
154+
def runTwoStatePure : Nat × Bool × Unit :=
155+
twoState
156+
|> State.run true
157+
|> State.run 4
158+
|> Prog.run
159+
160+
#guard runTwoStatePure = (5, false, ())
161+
162+
def runTwoStateIO : IO (Nat × Nat × Bool × Unit) := do
163+
let ref : IO.Ref Nat ← IO.mkRef 4
164+
let res ← twoState
165+
|> State.run true
166+
|> State.runViaIO ref
167+
|> IOEff.run
168+
-- Also check that the IO.Ref was updated
169+
(← ref.get, res) |> pure
170+
171+
/--
172+
info: (5, 5, false, ())
173+
-/
174+
#guard_msgs in
175+
#eval runTwoStateIO
81176

82177
end Examples

0 commit comments

Comments
 (0)