Определение Enumerator
:
type Enumerator a m b = Step a m b -> Iteratee a m b
В документации указано, что в то время как Iteratee
данные comsume, Enumerator
произведите его. Я могу понять, как можно создавать данные с таким типом:
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
не выполнял Continue
после отправки EOF
, вызывая ошибку, если это произойдет.)
А именно, Iteratee
создает Step
, когда он запускается с runIteratee
. Этот Step
затем подается в мой счетчик, который снабжает его Stream
, чтобы он мог продолжить. Мой перечислитель возвращает полученное продолжение.
Одна вещь выделяется на меня: этот код работает в монаде Iteratee
. Это означает, что он может потреблять данные, верно?
-- | 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
.
Мои вопросы:
-
Что произойдет, если вы попытаетесь "потреблять" данные в
Enumerator
, например,enumStreamWeird
? Откуда берутся данные? -
Даже если мы недостаточно сумасшедшие, чтобы потреблять данные в перечислителе, действительно ли он действителен для выполнения действий в основной монаде от имени перечислителя, а не от имени итератора, читающего данные, репродукция?
Последний вопрос может быть менее связан с моим главным вопросом, но я пытаюсь понять, как Enumerator
делает то, что он делает.