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
动作?
答案 0 :(得分:6)
run
(或run_
)Iteratee
预期输入并不是错误;这就是我们第一次传入enumEOF
的原因。收到EOF后,Iteratee
继续期待输入无效。http
的结果保留在Iteratee
monad中,您可以在同一个管道中执行多个操作,例如将两个HTTP响应流式传输到文件中。