Почему "http" в http-enumerator Iteratee?

Типичная подпись для http:

http :: MonadIO m
     => Request m
     -> (W.Status -> W.ResponseHeaders -> Iteratee S.ByteString m a)
     -> Manager
     -> Iteratee S.ByteString m a

Почему это не так?

http :: MonadIO m => … -> m a

Если я правильно понимаю, Iteratee x m a похож на монадический синтаксический анализатор, который потребляет поток элементов типа x. Для http обратного вызова имеет смысл быть Iteratee, поскольку он потребляет тело ответа.

Однако сам http не потребляет никакого ввода. Функция httpLbs выполняет http с run_ (определяется в Data.Enumerator). Из того, что я могу сказать, run считает это ошибкой, если заданный ей итератор ожидает ввода:

-- | Run an iteratee until it finishes, and return either the final value
-- (if it succeeded) or the error (if it failed).
run :: Monad m => Iteratee a m b
    -> m (Either Exc.SomeException b)
run i = do
    mStep <- runIteratee $ enumEOF ==<< i
    case mStep of
        Error err -> return $ Left err
        Yield x _ -> return $ Right x
        Continue _ -> error "run: divergent iteratee"

Итак, если http не потребляет вход, почему он итерационно? Почему это не просто действие MonadIO?

Ответ 1

  • Это не ошибка для передачи run (или run_) a Iteratee, которая ожидает ввода; почему мы сначала проходим в enumEOF. Он недействителен для Iteratee, чтобы продолжать ожидать ввода после получения EOF.
  • Оставив результат http в монаде Iteratee, вы можете выполнить несколько действий в одном конвейере, например потоковое воспроизведение двух ответов HTTP в файл.