I am working with the machines library and I have three Process
es
foo :: Process a b
bar :: Process b a
baz :: Process b c
I would like to compose them such that both bar
and baz
use the output of foo
as input. Moreover, and this is the part I'm struggling with, I would like to fed the output of bar
back into foo
, forming a cycle. Any hints on how to do it?
First you can use ~>
to compose processes sequentially (Process x y -> Process y z -> Process x z
), so the problem reduces to interpreting Process a a
, which you can do with a recursive function carrying a buffer. The buffer gets extended by Yield
and consumed by Await
. There is some arbitrariness in how you want to handle Await
on an empty buffer; here I just take the "no input" continuation and resume normally.
{-# LANGUAGE GADTs #-}
import Data.Machine
import Data.Machine.Process
loop :: Monad m => ProcessT m a a -> m ()
loop p = go [] p where
go :: Monad m => [a] -> ProcessT m a a -> m ()
go buffer p = runMachineT p >>= \s -> case s of
Stop -> pure ()
Yield o p -> go (buffer ++ [o]) p
Await p1 Refl p0 ->
case buffer of
[] -> go [] p0
i : buffer' -> go buffer' (p1 i)
loop3 :: Monad m => ProcessT m a b -> ProcessT m b c -> ProcessT m c a -> m ()
loop3 x y z = loop (x ~> y ~> z)
example :: ProcessT IO String String
example =
encased (Yield "world" (
encased (Await (\name ->
MachineT (putStrLn ("Hello " ++ name ++ "!") >> pure Stop)) Refl (error "No input"))))
main :: IO ()
main = loop example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With