@@ -24,6 +24,28 @@ Effect = (x : Type) -> Type -> (x -> Type) -> Type
24data EFFECT : Type where
24data EFFECT : Type where
25 MkEff : Type -> Effect -> EFFECT
25 MkEff : Type -> Effect -> EFFECT
27+-- 'sig' gives the signature for an effect. There are four versions
28+-- depending on whether there is no resource needed,
29+-- no state change, a non-dependent change,
30+-- or a dependent change. These are easily disambiguated by type.
32+namespace NoResourceEffect
33+ sig : Effect -> Type -> Type
34+ sig e r = e r () (\v => ())
36+namespace NoUpdateEffect
37+ sig : Effect -> (ret : Type) -> (resource : Type) -> Type
38+ sig e r e_in = e r e_in (\v => e_in)
40+namespace UpdateEffect
41+ sig : Effect -> (ret : Type) -> (res_in : Type) -> (res_out : Type) -> Type
42+ sig e r e_in e_out = e r e_in (\v => e_out)
44+namespace DepUpdateEffect
46+ (ret : Type) -> (res_in : Type) -> (res_out : ret -> Type) -> Type
47+ sig e r e_in e_out = e r e_in e_out
27||| Handler classes describe how an effect `e` is translated to the
49||| Handler classes describe how an effect `e` is translated to the
28||| underlying computation context `m` for execution.
50||| underlying computation context `m` for execution.
29class Handler (e : Effect) (m : Type -> Type) where
51class Handler (e : Effect) (m : Type -> Type) where
@@ -60,6 +82,7 @@ data SubList : List a -> List a -> Type where
60 Keep : SubList xs ys -> SubList (x :: xs) (x :: ys)
82 Keep : SubList xs ys -> SubList (x :: xs) (x :: ys)
61 Drop : SubList xs ys -> SubList xs (x :: ys)
83 Drop : SubList xs ys -> SubList xs (x :: ys)
63subListId : SubList xs xs
86subListId : SubList xs xs
64subListId {xs = Nil} = SubNil
87subListId {xs = Nil} = SubNil
65subListId {xs = x :: xs} = Keep subListId
88subListId {xs = x :: xs} = Keep subListId
@@ -133,26 +156,61 @@ relabel {xs = (MkEff a e :: xs)} l (v :: vs) = (l := v) :: relabel l vs
133||| @ x The return type of the result.
156||| @ x The return type of the result.
134||| @ es The list of allowed side-effects.
157||| @ es The list of allowed side-effects.
135||| @ ce Function to compute a new list of allowed side-effects.
158||| @ ce Function to compute a new list of allowed side-effects.
136−data Eff : (x : Type)
159+data EffM : (m : Type -> Type) -> (x : Type)
137− -> (es : List EFFECT)
160+ -> (es : List EFFECT)
138− -> (ce : x -> List EFFECT) -> Type where
161+ -> (ce : x -> List EFFECT) -> Type where
139− value : (val : a) -> Eff a (xs val) xs
162+ value : (val : a) -> EffM m a (xs val) xs
140− ebind : Eff a xs xs' ->
163+ ebind : EffM m a xs xs' ->
141− ((val : a) -> Eff b (xs' val) xs'') -> Eff b xs xs''
164+ ((val : a) -> EffM m b (xs' val) xs'') -> EffM m b xs xs''
142 callP : (prf : EffElem e a xs) ->
165 callP : (prf : EffElem e a xs) ->
143 (eff : e t a b) ->
166 (eff : e t a b) ->
144− Eff t xs (\v => updateResTy v xs prf eff)
167+ EffM m t xs (\v => updateResTy v xs prf eff)
146 liftP : (prf : SubList ys xs) ->
169 liftP : (prf : SubList ys xs) ->
147− Eff t ys ys' -> Eff t xs (\v => updateWith (ys' v) xs prf)
170+ EffM m t ys ys' -> EffM m t xs (\v => updateWith (ys' v) xs prf)
172+ new : Handler e' m => (e : EFFECT) -> resTy ->
173+ {auto prf : e = MkEff resTy e'} ->
174+ EffM m t (e :: es) (\v => e :: es) ->
175+ EffM m t es (\v => es)
149 (:-) : (l : ty) ->
177 (:-) : (l : ty) ->
150− Eff t [x] xs' -> -- [x] (\v => xs) ->
178+ EffM m t [x] xs' -> -- [x] (\v => xs) ->
151− Eff t [l ::: x] (\v => map (l :::) (xs' v))
179+ EffM m t [l ::: x] (\v => map (l :::) (xs' v))
181+-- Some type synonyms, so we don't always have to write EffM in full
184+ -- Simple effects, no updates
185+ Eff : (x : Type) -> (es : List EFFECT) -> Type
186+ Eff x es = {m : Type -> Type} -> EffM m x es (\v => es)
188+ EffT : (m : Type -> Type) -> (x : Type) -> (es : List EFFECT) -> Type
189+ EffT m x es = EffM m x es (\v => es)
192+ -- Dependent effects, updates not dependent on result
193+ Eff : (x : Type) -> (es : List EFFECT) -> (ce : List EFFECT) -> Type
194+ Eff x es ce = {m : Type -> Type} -> EffM m x es (\_ => ce)
196+ EffT : (m : Type -> Type) ->
197+ (x : Type) -> (es : List EFFECT) -> (ce : List EFFECT) -> Type
198+ EffT m x es ce = EffM m x es (\_ => ce)
201+ -- Dependent effects, updates dependent on result
202+ Eff : (x : Type) -> (es : List EFFECT)
203+ -> (ce : x -> List EFFECT) -> Type
204+ Eff x es ce = {m : Type -> Type} -> EffM m x es ce
206+ EffT : (m : Type -> Type) -> (x : Type) -> (es : List EFFECT)
207+ -> (ce : x -> List EFFECT) -> Type
208+ EffT m x es ce = EffM m x es ce
153%no_implicit
211%no_implicit
154−(>>=) : Eff a xs xs' ->
212+(>>=) : EffM m a xs xs' ->
155− ((val : a) -> Eff b (xs' val) xs'') -> Eff b xs xs''
213+ ((val : a) -> EffM m b (xs' val) xs'') -> EffM m b xs xs''
156(>>=) = ebind
214(>>=) = ebind
158-- namespace SimpleBind
216-- namespace SimpleBind
@@ -161,29 +219,29 @@ data Eff : (x : Type)
161-- (>>=) = ebind
219-- (>>=) = ebind
163||| Run a subprogram which results in an effect state the same as the input.
221||| Run a subprogram which results in an effect state the same as the input.
164−staticEff : Eff a xs (\v => xs) -> Eff a xs (\v => xs)
222+staticEff : EffM m a xs (\v => xs) -> EffM m a xs (\v => xs)
165staticEff = id
223staticEff = id
167||| Explicitly give the expected set of result effects for an effectful
225||| Explicitly give the expected set of result effects for an effectful
168||| operation.
226||| operation.
169−toEff : .(xs' : List EFFECT) -> Eff a xs (\v => xs') -> Eff a xs (\v => xs')
227+toEff : .(xs' : List EFFECT) -> EffM m a xs (\v => xs') -> EffM m a xs (\v => xs')
170toEff xs' = id
228toEff xs' = id
172−return : a -> Eff a xs (\v => xs)
230+return : a -> EffM m a xs (\v => xs)
173return x = value x
231return x = value x
175-- ------------------------------------------------------ [ for idiom brackets ]
233-- ------------------------------------------------------ [ for idiom brackets ]
177infixl 2 <*>
235infixl 2 <*>
179−pure : a -> Eff a xs (\v => xs)
237+pure : a -> EffM m a xs (\v => xs)
180pure = value
238pure = value
182−pureM : (val : a) -> Eff a (xs val) xs
240+pureM : (val : a) -> EffM m a (xs val) xs
183pureM = value
241pureM = value
185−(<*>) : Eff (a -> b) xs (\v => xs) ->
243+(<*>) : EffM m (a -> b) xs (\v => xs) ->
186− Eff a xs (\v => xs) -> Eff b xs (\v => xs)
244+ EffM m a xs (\v => xs) -> EffM m b xs (\v => xs)
187(<*>) prog v = do fn <- prog
245(<*>) prog v = do fn <- prog
189 return (fn arg)
247 return (fn arg)
@@ -203,7 +261,7 @@ execEff {e} {a} {res} {resk} (val :: env) (There p) eff k
203-- Q: Instead of m b, implement as StateT (Env m xs') m b, so that state
261-- Q: Instead of m b, implement as StateT (Env m xs') m b, so that state
204-- updates can be propagated even through failing computations?
262-- updates can be propagated even through failing computations?
206−eff : Env m xs -> Eff a xs xs' -> ((x : a) -> Env m (xs' x) -> m b) -> m b
264+eff : Env m xs -> EffM m a xs xs' -> ((x : a) -> Env m (xs' x) -> m b) -> m b
207eff env (value x) k = k x env
265eff env (value x) k = k x env
208eff env (prog `ebind` c) k
266eff env (prog `ebind` c) k
209 = eff env prog (\p', env' => eff env' (c p') k)
267 = eff env prog (\p', env' => eff env' (c p') k)
@@ -211,6 +269,8 @@ eff env (callP prf effP) k = execEff env prf effP k
211eff env (liftP prf effP) k
269eff env (liftP prf effP) k
212 = let env' = dropEnv env prf in
270 = let env' = dropEnv env prf in
213 eff env' effP (\p', envk => k p' (rebuildEnv envk prf env))
271 eff env' effP (\p', envk => k p' (rebuildEnv envk prf env))
272+eff env (new (MkEff resTy newEff) res {prf=Refl} effP) k
273+ = eff (res :: env) effP (\p', (val :: envk) => k p' envk)
215-- xs is needed explicitly because otherwise the pattern binding for
275-- xs is needed explicitly because otherwise the pattern binding for
216-- 'l' appears too late. Solution seems to be to reorder patterns at the
276-- 'l' appears too late. Solution seems to be to reorder patterns at the
@@ -235,14 +295,14 @@ call : {a, b: _} -> {e : Effect} ->
235 (eff : e t a b) ->
295 (eff : e t a b) ->
236 {default tactics { search 100; }
296 {default tactics { search 100; }
237 prf : EffElem e a xs} ->
297 prf : EffElem e a xs} ->
238− Eff t xs (\v => updateResTy v xs prf eff)
298+ EffM m t xs (\v => updateResTy v xs prf eff)
239call e {prf} = callP prf e
299call e {prf} = callP prf e
242−lift : Eff t ys ys' ->
302+lift : EffM m t ys ys' ->
243 {default tactics { search 100; }
303 {default tactics { search 100; }
244 prf : SubList ys xs} ->
304 prf : SubList ys xs} ->
245− Eff t xs (\v => updateWith (ys' v) xs prf)
305+ EffM m t xs (\v => updateWith (ys' v) xs prf)
246lift e {prf} = liftP prf e
306lift e {prf} = liftP prf e
@@ -255,7 +315,7 @@ lift e {prf} = liftP prf e
256||| @prog The effectful program to run.
316||| @prog The effectful program to run.
257run : Applicative m => {default MkDefaultEnv env : Env m xs}
317run : Applicative m => {default MkDefaultEnv env : Env m xs}
258− -> (prog : Eff a xs xs') -> m a
318+ -> (prog : EffM m a xs xs') -> m a
259run {env} prog = eff env prog (\r, env => pure r)
319run {env} prog = eff env prog (\r, env => pure r)
261||| Run an effectful program in the identity context.
321||| Run an effectful program in the identity context.
@@ -264,7 +324,7 @@ run {env} prog = eff env prog (\r, env => pure r)
264||| The `env` argument is implicit and initialised automatically.
324||| The `env` argument is implicit and initialised automatically.
266||| @prog The effectful program to run.
326||| @prog The effectful program to run.
267−runPure : {default MkDefaultEnv env : Env id xs} -> (prog : Eff a xs xs') -> a
327+runPure : {default MkDefaultEnv env : Env id xs} -> (prog : EffM id a xs xs') -> a
268runPure {env} prog = eff env prog (\r, env => r)
328runPure {env} prog = eff env prog (\r, env => r)
270||| Run an effectful program in a given context `m` with a default value for the environment.
330||| Run an effectful program in a given context `m` with a default value for the environment.
@@ -273,7 +333,7 @@ runPure {env} prog = eff env prog (\r, env => r)
274||| @env The environment to use.
334||| @env The environment to use.
275||| @prog The effectful program to run.
335||| @prog The effectful program to run.
276−runInit : Applicative m => (env : Env m xs) -> (prog : Eff a xs xs') -> m a
336+runInit : Applicative m => (env : Env m xs) -> (prog : EffM m a xs xs') -> m a
277runInit env prog = eff env prog (\r, env => pure r)
337runInit env prog = eff env prog (\r, env => pure r)
279||| Run an effectful program with a given default value for the environment.
339||| Run an effectful program with a given default value for the environment.
@@ -282,31 +342,31 @@ runInit env prog = eff env prog (\r, env => pure r)
283||| @env The environment to use.
343||| @env The environment to use.
284||| @prog The effectful program to run.
344||| @prog The effectful program to run.
285−runPureInit : (env : Env id xs) -> (prog : Eff a xs xs') -> a
345+runPureInit : (env : Env id xs) -> (prog : EffM id a xs xs') -> a
286runPureInit env prog = eff env prog (\r, env => r)
346runPureInit env prog = eff env prog (\r, env => r)
288−runWith : (a -> m a) -> Env m xs -> Eff a xs xs' -> m a
348+runWith : (a -> m a) -> Env m xs -> EffM m a xs xs' -> m a
289runWith inj env prog = eff env prog (\r, env => inj r)
349runWith inj env prog = eff env prog (\r, env => inj r)
291−runEnv : Applicative m => Env m xs -> Eff a xs xs' ->
351+runEnv : Applicative m => Env m xs -> EffM m a xs xs' ->
292 m (x : a ** Env m (xs' x))
352 m (x : a ** Env m (xs' x))
293runEnv env prog = eff env prog (\r, env => pure (r ** env))
353runEnv env prog = eff env prog (\r, env => pure (r ** env))
295-- ----------------------------------------------- [ some higher order things ]
355-- ----------------------------------------------- [ some higher order things ]
297−mapE : (a -> {xs} Eff b) -> List a -> {xs} Eff (List b)
357+mapE : (a -> {xs} EffM m b) -> List a -> {xs} EffM m (List b)
298mapE f [] = pure []
358mapE f [] = pure []
299mapE f (x :: xs) = [| f x :: mapE f xs |]
359mapE f (x :: xs) = [| f x :: mapE f xs |]
302−mapVE : (a -> {xs} Eff b) ->
362+mapVE : (a -> {xs} EffM m b) ->
303 Vect n a ->
363 Vect n a ->
304− {xs} Eff (Vect n b)
364+ {xs} EffM m (Vect n b)
305mapVE f [] = pure []
365mapVE f [] = pure []
306mapVE f (x :: xs) = [| f x :: mapVE f xs |]
366mapVE f (x :: xs) = [| f x :: mapVE f xs |]
309−when : Bool -> Lazy ({xs} Eff ()) -> {xs} Eff ()
369+when : Bool -> Lazy ({xs} EffM m ()) -> {xs} EffM m ()
310when True e = Force e
370when True e = Force e
311when False e = pure ()
371when False e = pure ()