Open Lysxia opened 4 months ago
Ah, this is very interesting. I am looking for ways that we can make dynamic effect definition easier. Could you add an example to confirm this works when the handler is implemented in terms of another effect? For example, define the MyReader
effect in terms of State
(it just gets the current value of the State
)? (I appreciate that's not really a "reader" any more, but for the sake of argument ... .)
Could you add an example to confirm this works when the handler is implemented in terms of another effect?
In fact, if you can demonstrate runFileSystemPure
using this technique, that would be ideal.
Here's what it looks like to write a handler with more than one operation in the context of more than one other handler. We'll need an ergonomic way of dealing with repeated insertSecond
s, but otherwise this looks good.
data MyReader r m =
MkMyReader { myAsk :: m r,
myAsk2 :: Int -> m r
}
instance CovariantSig (MyReader r) where
smap f h =
MkMyReader { myAsk = f (myAsk h), myAsk2 = fmap f (myAsk2 h) }
runMyReader ::
r ->
(forall s0. H.Handle (MyReader r) s0 -> Eff (s0 :& s) a) ->
Eff s ([Int], a)
runMyReader r k =
evalState r $ \st -> do
yieldToList $ \y -> do
with
(MkMyReader { myAsk = get st,
myAsk2 = \i -> yield y i *> get st })
(\rr -> insertSecond (insertSecond (k rr)))
local
is missing.
Let's continue the discussion about higher-order effects at https://github.com/tomjaguarpaw/bluefin/issues/15.
Very nice, thanks! I'll have a bit of a play, implement some other example with it, and rewrite Bluefin.Compound
.
(I took the liberty of rebasing on master
and fixing a conflict.)
I'm still waiting for a time when I can look at this properly, but it's one of my highest priority items.
Wow, I found a very nice way of defining this style of handler within any level of enclosing handlers! (within
). I think this is very close to becoming the "official" way of creating new effects. Before that I need to confirm it's compatible with https://github.com/tomjaguarpaw/bluefin/issues/17.
(and rebased on master
)
Based on your suggestion on the cleff issue tracker https://github.com/re-xyr/cleff/issues/31
I mainly wanted to show an implementation that allows the record field selectors to be used directly, so you don't need to declare operations as separate functions.
I specialized the name of the
CovariantSig
class, but of course it's just one of thoseHFunctor
elsewhere.As I mentioned on Discourse, this is an interface that is forwards-compatible with algebraic effects while being hopefully useful on its own as a restricted form of effect handlers ("tail-resumptive"). In effectful-core, this corresponds to the
Dispatch.Static
module.I tried to avoid the word "handler" (which can be too easily overloaded), instead sticking to the word "handle" as in "handle-pattern".