import Network.HTTP.Conduit
import qualified Data.HashMap.Lazy as LHashMap
import Network.HTTP.Types
getJSONObject :: String -> IO Object
--.............
main = do
jsonObject <- getJSONObject "example.com"
String a <- LHashMap.lookup "some_key" jsonObject -- doesn't compile
--.....................................
错误是:
Couldn't match type `Maybe' with `IO'
Expected type: IO Value
Actual type: Maybe Value
确实,LHashMap.lookup
会返回Maybe
,而不是IO
。但<-
Monads
不应该使用Maybe
吗?
我如何使它工作?
更新: 根据上面的错误,由于同样的事情,下面的代码不起作用:
let toPrint = do
Object jsonObject <- decode $ responseBody res :: Maybe Value
Object jsonObject2 <- LHashMap.lookup "key1" jsonObject
Object jsonObject3 <- LHashMap.lookup "key2" jsonObject2
Array d <- LHashMap.lookup "key3" jsonObject3
String val <- return $ d ! 1
return val
case toPrint of
Just a -> IO.putStrLn a
_ -> error "Unexpected JSON"
但确实有效。
答案 0 :(得分:6)
所有附加值中的monadic值都必须来自同一个Monad。如果你贬低这个记号,很容易看到这个:
main = getJSONObject "example.com" >>= (\jsonObject ->
LHashMap.lookup "some_key" jsonObject >>= (\String a -> ... ))
查看>>=
>>= :: Monad m => m a -> (a -> m b) -> m b
请注意,尽管参数m
使>>=
具有多态性,但对于两个参数和返回值,它都是相同的m
。
特别是,这意味着类型检查器要求getJSONObject "example.com"
返回LHashMap.lookup "some_key" jsonObject >>= (\String a -> ...)
所在的同一个monad中的值,这要求LHashMap.lookup "some_key" jsonObject
位于同一个monad中。因此你的错误。
您需要弄清楚如何处理失败:
您可以使用let
语句而不是绑定(不推荐)将其设置为模式匹配例外:
% cat Temp.hs
module Main where
main = do
let Just x = Nothing
putStrLn $ "Hello " ++ x
% runhaskell Temp.hs
Temp.hs: Temp.hs:4:7-22: Irrefutable pattern failed for pattern Data.Maybe.Just x
%
你可以把它变成IO monad的失败,这会使它变成一个稍微不同的例外(也不推荐)n
% cat Temp.hs
module Main where
main = do
Just x <- return Nothing
putStrLn $ "Hello " ++ x
% runhaskell Temp.hs
Temp.hs: user error (Pattern match failure in do expression at Temp.hs:4:3-8)
%
您可以使用case
语句(推荐):
% cat Temp.hs
module Main where
main = do
case Nothing of
Nothing -> return ()
Just x -> putStrLn $ "Hello " ++ x
% runhaskell Temp.hs
%
答案 1 :(得分:5)
在do
区块中,你使用的monad意味着是同质的,因为它不需要
(>>=) :: Monad m => m a -> (a -> m b) -> m b
由于m
在整个绑定过程中是一致的,因此我们在整个块中也必须与它保持一致。
这里正确的解决方案是以纯粹的方式处理maybe
,而不是单独处理它#34;。一个简单的解决方案可能就是使用案例表达式
case LHashMap.lookup "some_key" jsonObject of
Just res -> some IO here
Nothing -> handle failure here
或者只是将其粉碎成带有
的表达式 maybe :: b -> (a -> b) -> Maybe a -> b