有人可以解释为什么我不能这样做:
getHeaders :: String -> IO ResponseHeaders
getHeaders url = parseUrl url >>= withManager . httpLbs >>= responseHeaders
--getHeaders url = parseUrl url >>= (\x -> withManager $ httpLbs x) >>= responseHeaders -- doesn't compiler either
并且必须这样做:
getHeaders url = do
req <- parseUrl url
res <- withManager $ httpLbs req
return $ responseHeaders res
由于错误:
Couldn't match type `[]' with `IO'
Expected type: Response Data.ByteString.Lazy.Internal.ByteString
-> IO ResponseHeaders
Actual type: Response Data.ByteString.Lazy.Internal.ByteString
-> ResponseHeaders
In the second argument of `(>>=)', namely `responseHeaders'
In the expression:
parseUrl url >>= withManager . httpLbs >>= responseHeaders
有没有办法让它与>>=
合作,而不是do
?
更新
确实,添加返回会使其有效。但是,我不明白为什么我可以链接它们,因为它们有不同类型的Monads。就我而言,它们不能与>>=
链接,因为左表达式的返回类型与右表达式接受的输入不同。看:
http://hackage.haskell.org/package/http-conduit-1.2.4/docs/Network-HTTP-Conduit.html#v:parseUrl
parseUrl :: Failure HttpException m => String -> m (Request m')
withManager :: ResourceIO m => (Manager -> ResourceT m a) -> m a
答案 0 :(得分:7)
您使用>>=
忘记了翻译中的回复。正确的代码是:
getHeaders url = parseUrl url >>= withManager . httpLbs >>= return . responseHeaders
这是必需的,因为(>>=) :: IO a -> (a -> IO b) -> IO b
,但在您的情况下,responseHeaders
会返回ResponseHeaders
类型的值,该值与IO b
不匹配。通过回归,你可以解除&#34; IO monad中的值,因此您得到IO ResponseHeaders
且类型匹配。
但是,因为a >>= return . f
对于所有fmap f a
和f
等于a
,所以这也可以写成:
parseUrl url = fmap responseHeaders $ parseUrl url >>= withManager . httpLbs
答案 1 :(得分:1)
responseHeaders
返回ResponseHeaders
,同时您需要在上次拨打IO responseHeaders
时返回>>=
。
您可以使用:
getHeaders url = parseUrl url >>= withManager . httpLbs >>= (return . responseHeaders)