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