我正试图弄清楚 Conduits 是如何工作的,并且正陷入所涉及的 monads 和 transformers 中。
我将一些示例代码归结为以下内容,它有效:
import Control.Monad.Trans.Class (lift)
import Data.Conduit
import Data.Conduit.Binary (sinkFile)
import Data.Conduit.List
import Network.HTTP.Conduit
downloadContent manager = do
mx <- await
case mx of
Nothing -> return ()
Just name -> do
req <- lift $ parseUrl $ "http://" ++ name ++ ".com/"
res <- lift $ http req manager
lift $ responseBody res $$+- sinkFile $ name ++ ".html"
downloadContent manager
main = do
runResourceT $ do
withManager $ \manager -> do
sourceList ["google", "yahoo"] $$ downloadContent manager
我不明白为什么我需要在lift
里面downloadContent
。为什么我需要lift
在上面的代码中使用?我从什么地方搬来搬去?如果我看签名:
parseUrl
:: failure-0.2.0.1:Control.Failure.Failure HttpException m =>
String -> m (Request m')
http
:: (MonadResource m, MonadBaseControl IO m) =>
Request m
-> Manager
-> m (Response
(ResumableSource m Data.ByteString.Internal.ByteString))
($$+-) :: Monad m => ResumableSource m a -> Sink a m b -> m b
downloadContent
:: (MonadResource m, MonadBaseControl IO m,
failure-0.2.0.1:Control.Failure.Failure HttpException m) =>
Manager -> ConduitM [Char] o m ()
class (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource m
这并不能真正帮助我理解正在发生的事情。