如果枚举器尝试消耗输入会发生什么?

Joe*_*ams 19 haskell iterate

定义Enumerator是:

type Enumerator a m b = Step a m b -> Iteratee a m b
Run Code Online (Sandbox Code Playgroud)

该文档指出,虽然Iteratees comsume数据,Enumerators产生它.我可以理解如何使用这种类型生成数据:

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
Run Code Online (Sandbox Code Playgroud)

(enumEOF比这更复杂......这显然是检查,以确保IterateeContinue被发出后EOF,抛如果它的错误.)

即,Iterateea Step运行时生成a runIteratee.这Step是再喂到我的枚举,其与供应它Stream,使其能够继续.我的枚举器返回结果延续.

有一点让我很突出:这个代码在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
Run Code Online (Sandbox Code Playgroud)

文档说明当枚举器同时充当源和接收器时,Enumeratee应该使用:

type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)
Run Code Online (Sandbox Code Playgroud)

但是,显然我没有; 我可以在an的定义中使用输入Enumerator,如我的enumStreamWeird函数所示.

我的问题是:

  • 如果你尝试"消耗"内的数据会发生什么Enumerator,像enumStreamWeird呢?数据来自哪里?

  • 即使我们没有足够的疯狂来消耗枚举器中的数据,代表枚举器在底层monad中执行操作是否有效,而不是代表迭代器读取我们正在生成的数据?

后一个问题可能与我的主要问题不太相关,但我试图理解Enumerator它是如何做的.

小智 1

枚举器消耗数据没有任何问题。它是一个 iteratee 转换器,很可能将自己的输入输入到 iteratee 中。查看将枚举器应用于迭代器的方式。您还可以将另一个枚举器应用于应用于枚举器的迭代器。