问题描述
我正在使用 machines 库,我有三个 Process
es
foo :: Process a b
bar :: Process b a
baz :: Process b c
我想将它们组合成 bar
和 baz
都使用 foo
的输出作为输入。此外,这是我正在努力解决的部分,我想将 bar
的输出反馈回 foo
,形成一个循环。有关如何操作的任何提示?
解决方法
首先,您可以使用 ~>
顺序组合进程 (Process x y -> Process y z -> Process x z
),因此问题简化为解释 Process a a
,您可以使用带有缓冲区的递归函数来完成。缓冲区被 Yield
扩展并被 Await
消耗。在空缓冲区上处理 Await
的方式有些随意;在这里,我只是采用“无输入”延续并正常恢复。
{-# 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