免责声明:我不太了解迭代器,也从未使用过它们。所以,我的回答持保留态度。
这个定义等同于 Oleg 的(更准确地说,它是 CPS 风格的求和),但有一点不同:它保证访问迭代对象总是返回一个单子值。
这是奥列格的定义:
data Iteratee el m a =
| IE_done a
| IE_cont (Maybe ErrMsg)
(Stream el -> m (Iteratee el m a, Stream el))
所以它是两者的总和done a
,我们完成了一个给a
定的结果,或者cont (Maybe ErrMsg) (Stream el -> ...)
:一种在给定另一块输入的情况下继续迭代的方法,并且可能是一个错误(在这种情况下继续继续相当于重新开始计算)。
众所周知,这Either a b
相当于forall r. (a ->
r) -> (b -> r) -> r
:给你一个a
或b
相当于向你保证,对于你可能想出的任何结果r
转换a
和转换,我将能够产生这样一个(要做到这一点,我必须有一或一)。从某种意义上说,(Either ab)
引入了一个数据,并消除了
这个数据:如果这样的函数被命名为,那么就相当于对 some进行模式匹配。b
r
a
b
r. (a -> r) -> (b -> r) -> r
case_ab
case_ab (\a ->
foo_a) (\b -> foo_b)
case
ab of { Left a -> foo_a; Right b -> foo_b }
ab :: Either a b
所以这里是延续(我们在这里谈论延续是因为
(a -> r)
表示“一旦我们知道它是一个值会发生什么a
”)相当于奥列格的定义:
data Iteratee el m a =
forall r.
(a -> r) ->
((Maybe ErrMsg), (Stream el -> m (Iteratee el m a, Stream el)) -> r) ->
r
但是 iteratee 的定义有一个转折(以一些无害的柯里化为模):结果不是r
but m r
:在某种意义上,我们强制我们的 iteratee 上的模式匹配结果始终存在于 monad 中
m
。
data Iteratee el m a =
forall r.
(a -> m r) ->
(Maybe ErrMsg -> (Stream el -> m (Iteratee el m a, Stream el)) -> m r) ->
m r
最后,请注意 Oleg 定义中的“继续迭代”数据是Stream .. -> m (Iterate .., Stream ..)
,而在 iteratee 包中它只是Stream -> Iteratee
。我假设他们在这里删除了 monad,因为他们在外部级别强制执行它(如果您应用 iteratee,您将被迫生活在 monad 中,那么为什么还要强制后续计算生活在 monad 中?)。我不知道为什么Stream
不再有输出,我想这意味着那些 Iteratee 必须在可用时消耗所有输入(或在返回类型中编码“尚未完成”逻辑a
)。也许这是出于效率原因。