在一个循环中组合机器

问题描述

我正在使用 machines 库,我有三个 Processes

foo :: Process a b

bar :: Process b a

baz :: Process b c

我想将它们组合成 barbaz 都使用 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