机器交替地从输入流中Mealy
读取a并将 a 输出到输出流。它首先读取,然后在每次读取后输出一次。a
a
b
newtype Mealy a b = Mealy { runMealy :: a -> (b, Mealy a b) }
Moore
机器交替地将 a 输出到b
输出流并从输入流中读取a
输入。它以 的输出开始,b
然后在每次输出后读取一次。
data Moore a b = Moore b (a -> Moore a b)
FST 要么从其输入读取、写入其输出,要么停止。它可以根据需要连续读取任意多次,也可以根据需要连续写入任意多次。
data FST a b
= Read (a -> FST a b)
| Write (b, FST a b)
| Stop
FST
from 机器的等价物是Process
. 它的定义有点分散。为了简化讨论,我们将暂时忘记Process
并从内到外探索它。
基函子
为了描述 aProcess
是什么,我们将首先注意到到目前为止所有三台机器中的一个模式。它们中的每一个都递归地引用自己的“下一步做什么”。我们将用任何类型替换“下一步做什么” next
。Mealy
机器在将输入映射到输出的同时,还提供机器next
运行。
newtype MealyF a b next = MealyF { runMealyF :: a -> (b, next) }
Moore
机器在输出并请求输入后,计算出要运行的机器next
。
data MooreF a b next = MooreF b (a -> next)
我们也可以FST
这样写。当我们Read
从输入中我们将根据输入找出要做什么next
。当我们Write
输出时,我们还将提供next
输出后要做什么。当我们Stop
接下来无事可做时。
data FSTF a b next
= Read (a -> next)
| Write (b, next)
| Stop
这种消除显式递归的模式在 Haskell 代码中反复出现,通常称为“基本函子”。在机器包中,基本函子是Step
. 与我们的代码相比,Step
已将输出的类型变量重命名为o
、下一步做什么r
、读取到Await
和写入到Yield
。
data Step k o r
= forall t. Await (t -> r) (k t) r
| Yield o r
| Stop
Await
ing 比Read
aMachine
可以从多个来源读取要复杂一些。对于Process
只能从单一来源读取的es,k
适用Is
于特定类型,这是对第二种类型Is
第一种类型的证明。对于一个Process
读数输入a
,k
将是Is a
。
data Step (Is a) o r
= forall t. Await (t -> r) (Is a t) r
| Yield o r
| Stop
存在量化forall t.
是处理Source
s的实现细节。目睹a ~ t
这成为之后。
data Step (Is a) o r
= forall t ~ a. Await (t -> r) Refl r
| Yield o r
| Stop
如果我们统一t
并a
删除Refl
始终相同的构造函数,这看起来像我们的FSTF
.
data Step (Is a) o r
= Await (a -> r) r
| Yield o r
| Stop
r
下一步做什么的额外内容Await
是当没有更多输入时下一步做什么。
机器变压器`MachineT`
机器变压器,MachineT
,Step
看起来几乎像我们的FST
。它说:“在某个 monad 上运行的机器m
是在那个 monad 中做什么才能获得下一个Step
..next
每一步之后要做的事情是另一个MachineT
.”
newtype MachineT m k o = MachineT { runMachineT :: m (Step k o (MachineT m k o)) }
总的来说,专门针对我们的类型,这看起来像
newtype MachineT m (Is a) o =
MachineT m (
Await (a -> MachineT m (Is a) o) (MachineT m (Is a) o)
| Yield o (MachineT m (Is a) o)
| Stop
)
Machine
是一个纯粹的MachineT
。
type Machine k o = forall m. Monad m => MachineT m k o
Monad
对所有s 的通用量化m
是另一种说法,即计算不需要来自底层的任何东西Monad
。这可以通过替换来Identity
看到m
。
type Machine k o =
MachineT Identity (
Await (a -> MachineT Identity k o) (MachineT Identity k o)
| Yield o (MachineT Identity k o)
| Stop
)
流程
A Process
orProcessT
是一个Machine
or MachineT
,它只读取单一类型的输入a
, Is a
。
type Process a b = Machine (Is a) b
type ProcessT m a b = MachineT m (Is a) b
Process
在删除所有始终相同的中间构造函数后,A具有以下结构。这个结构与我们的 完全相同FST
,只是在没有更多输入的情况下添加了“下一步做什么”。
type Process a b =
Await (a -> Process a b) (Process a b)
| Yield b (Process a b)
| Stop
该ProcessT
变体周围有一个m
包裹,因此它可以在每个步骤中在单子中起作用。
Process
模型状态传感器。