我现在对其余的箭头机械相当满意,但我不明白循环是如何工作的。这对我来说似乎很神奇,这对我的理解不利。我也很难理解 mfix。当我查看在rec
a proc
ordo
块中使用的一段代码时,我会感到困惑。使用常规的 monadic 或箭头代码,我可以逐步完成计算并在脑海中保持对正在发生的事情的操作画面。当我到达时rec
,我不知道要保留什么图片!我被卡住了,我无法推理这样的代码。
我试图理解的例子来自罗斯帕特森关于箭头的论文,关于电路的论文。
counter :: ArrowCircuit a => a Bool Int
counter = proc reset -> do
rec output <- returnA -< if reset then 0 else next
next <- delay 0 -< output+1
returnA -< output
我假设如果我理解了这个例子,我将能够理解循环,这将有助于理解 mfix。他们对我的感觉基本相同,但也许我错过了一个微妙之处?无论如何,我真正想要的是这些代码片段的操作图,所以我可以像“常规”代码一样在脑海中逐步浏览它们。
编辑:感谢Pigworker的回答,我开始考虑rec之类的要求得到满足。举counter
个例子,rec 块的第一行需要一个名为 的值output
。我想象这在操作上是创建一个盒子,给它贴标签output
,然后让 rec 块填充那个盒子。为了填充该框,我们向 returnA 输入一个值,但该值本身需要另一个值,称为next
. 为了使用这个值,必须在 rec 块中要求另一行,但现在在 rec 块中的哪个位置要求它并不重要。
所以我们转到下一行,找到标有 的框next
,我们要求另一个计算填充它。现在,这个计算需要我们的第一个盒子!所以我们给它 box,但它里面没有任何值,所以如果这个计算需要 的内容output
,我们就会进入一个无限循环。幸运的是,延迟获取了盒子,但在不查看盒子内部的情况下产生了一个值。这填充next
,然后允许我们填充output
。现在output
已填充,当处理该电路的下一个输入时,前一个output
框将具有其值,准备好被要求以产生下一个next
,从而产生下一个output
。
听起来怎么样?