Closed treeowl closed 9 years ago
Note: the type of fitM
suggests it could do this job, but flip evalStateT s
is not a monad morphism; the state will never change.
Somehow I think that kind of thing should happen at the PlanT
level. PlanT
supports MonadState
if my memory serves me right.
This might go well with a function of type Monad m => (i -> ProcessT m i o) -> ProcessT m i o
, which I've used previously to initialize Attoparsec parsers.
@YoEight, PlanT k o m
is only MonadState
if m
is. I'm not actually sure if the conversion I'm talking about even makes sense for a PlanT
, except in the process of converting it to a MachineT
. Also remember that not every MachineT
comes from a PlanT
. They can be built with <>
and ~>
and all sorts of other fun things.
Are you asking for the same kind of stateful combinators pipes
has (or used to have) for instance ?
@YoEight, I know pretty much nothing about pipes
. It's possible to make stateful machines by doing things like
blah = construct . flip runStateT s0 $ forever go
where
go = do
x <- lift await
blah blah blah
lift (yield foo)
or else manually with
blah = construct (go s0)
where
go s = do
x <- await
whatever
yield foo
go s1
The looping must be done within the PlanT
itself. With the function I proposed, you can instead write things like
blah = fob s0 $ boom ~> (repeatedly $ do
x <- await
whatever
yield foo)
@YoEight, someone pointed me toward Pipes.Lift.runStateP
. This is actually more like execStateP
.
Interesting. I presume we wind up more execStateP
-like because we have no final result type to put the answer state into?
Correct. We might be able to play games with Either or something, but it's not obvious to me what makes sense there, so I'm not proposing anything. I'm fairly sure the execStateP analogue (execStateM?) is sane. We could also add runReaderM e = fitM (flip runReaderT e) for completeness. I pondered whether there's anything useful to do with ContT, but reached no definite conclusion. On Aug 24, 2015 12:46 PM, "Edward Kmett" notifications@github.com wrote:
Interesting. I presume we wind up more execStateP-like because we have no final result type to put the answer state into?
— Reply to this email directly or view it on GitHub https://github.com/ekmett/machines/issues/59#issuecomment-134296062.
We can also port some exception handling from pipes
. I think this is probably right:
catchExcept :: Monad m
=> MachineT (ExceptT e m) k o
-> (e -> MachineT (ExceptT e m) k o)
-> MachineT (ExceptT e m) k o
catchExcept m c =
MachineT $ do
step <- E.catchE (runMachineT m) (\e -> runMachineT (catchExcept (c e) c))
case step of
Stop -> return Stop
Yield o m' -> return $ Yield o (catchExcept m' c)
Await f k m' -> return $ Await (flip catchExcept c . f) k (catchExcept m' c)
I have the feeling there's some simpler way to handle this.
Added in #61
I think something like this should work, with a saner name, but I haven't tested it. I don't know if something like this is available for plans;
PlanT
confuses the heck out of me.