Why is `http` in http-enumerator an Iteratee?
質問
The type signature for http
is:
http :: MonadIO m
=> Request m
-> (W.Status -> W.ResponseHeaders -> Iteratee S.ByteString m a)
-> Manager
-> Iteratee S.ByteString m a
Why isn't it this instead?
http :: MonadIO m => … -> m a
If I understand correctly, an Iteratee x m a
is like a monadic parser that consumes a stream of items of type x
. It makes sense for http
's callback to be an Iteratee
, as it consumes the response body.
However, http
itself does not appear to consume any input. The httpLbs function executes http
with run_
(defined in Data.Enumerator). From what I can tell, run
considers it an error if the iteratee given to it expects input:
-- | 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"
So if http
does not consume input, why is it an iteratee? Why isn't it just a MonadIO
action?
解決
- It's not an error to pass
run
(orrun_
) anIteratee
that expects input; that's why we first pass inenumEOF
. It's invalid for anIteratee
to continue expecting input after receiving an EOF. - By leaving the result of
http
in theIteratee
monad, you can perform multiple actions in the same pipeline, such as streaming two HTTP responses into a file.
所属していません StackOverflow