Open treeowl opened 9 years ago
I think this works, but there's almost certainly a nicer way to do it:
runHead :: forall m k b . Monad m => MachineT m k b -> m (Maybe b)
runHead (MachineT m) = m >>= \case
Stop -> return Nothing
Yield o k -> runT_ k >> return (Just o)
Await _ _ e -> runHead e
Makes sense to me.
Linking in taking 1
or construct (yield =<< await)
would be a nice way to avoid driving into Step
in an example.
@glguy, I actually think the runner I proposed is sufficiently useful to add to the library as runT1
. There are also sensible folding runners that run machines to completion and fold over the results.
We also have Data.Machine.Process.fold which can be linked to the end of a Process to fold all the results into one already.
@glguy, D.M.P.fold
and fold1
are what makes runT1
useful—it gives a sensible way to get the result of such machines. However, fold
is a bit annoying in that it always produces exactly one result, but the type system doesn't know that, which brings in horrors like head
or fromJust
. Having a folding machine runner gets around that problem.
If I understand the situation properly, this should work just fine as applied in the example, but it seems a terrible example in and of itself. Aside from the partiality problem, my understanding is that
runT
accumulates a list whether the list is ever used or not. The right thing, presumably, is to build a machine that passes the first result through to the end.