的定义Enumerator是:
type Enumerator a m b = Step a m b -> Iteratee a m b
该文档指出,虽然Iteratees 消费数据,Enumerator但 s 生产它。我可以理解如何使用这种类型生成数据:
enumStream :: (Monad m) => Stream a -> Enumerator a m b
enumStream stream step =
case step of
Continue k -> k stream
_ -> returnI step -- Note: 'stream' is discarded
(enumEOF比这更复杂......它显然会检查以确保在被给予之后没有Iteratee,如果是则抛出错误。)ContinueEOF
即, an在运行时Iteratee会产生 a 。然后将其馈送到我的枚举器,它为它提供 a以便它可以继续。我的枚举器返回结果延续。SteprunIterateeStepStream
有一件事让我印象深刻:这段代码在Iterateemonad 中运行。这意味着它可以消耗数据,对吧?
-- | Like 'enumStream', but consume and discard a chunk from the input stream
-- simply because we can.
enumStreamWeird :: (Monad m) => Stream a -> Enumerator a m b
enumStreamWeird stream step = do
_ <- continue return -- Look, mommy, I'm consuming input!
case step of
Continue k -> k stream
_ -> returnI step
该文档指出,当枚举器同时充当源和接收器时,Enumeratee应改为使用:
type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)
但是,显然我不必这样做;Enumerator正如我的enumStreamWeird函数所示,我可以在 an 的定义中使用输入。
我的问题是:
如果您尝试在 中“使用”数据,会发生什么
Enumerator情况enumStreamWeird?数据从何而来?即使我们没有足够疯狂地使用枚举器中的数据,代表枚举器而不是代表迭代器读取我们正在生成的数据在底层 monad 中执行操作是否有效?
后一个问题可能与我的主要问题不太相关,但我试图了解 anEnumerator它是如何做的。