为什么http-enumerator中的`http`是Iteratee?

时间:2011-10-03 17:12:18

标签: haskell iterate

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就像一个monadic解析器,它使用x类型的项目流。 http的回调是Iteratee是有道理的,因为它会占用响应主体。

但是,http本身似乎不消耗任何输入。 httpLbs函数使用run_(在Data.Enumerator中定义)执行http。据我所知,如果赋予它的iteratee需要输入,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 个答案:

答案 0 :(得分:6)

  1. 传递run(或run_Iteratee预期输入并不是错误;这就是我们第一次传入enumEOF的原因。收到EOF后,Iteratee继续期待输入无效。
  2. 通过将http的结果保留在Iteratee monad中,您可以在同一个管道中执行多个操作,例如将两个HTTP响应流式传输到文件中。