此功能(使用httpLBS)有效:
makeRequest = do
response <- httpLBS "http://httpbin.org/get"
putStrLn $ "The status code was: " ++ show (getResponseStatusCode response)
但是这个函数(使用httpJSON)不会:
makeRequest = do
response <- httpJSON "http://httpbin.org/get"
putStrLn $ "The status code was: " ++ show (getResponseStatusCode response)
它抛出错误:
Ambiguous type variable `a0' arising from a use of `httpJSON' prevents the constraint
`(aeson-1.1.2.0:Data.Aeson.Types.FromJSON.FromJSON a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
答案 0 :(得分:11)
比较httpLBS
和httpJSON
的类型:
httpLBS :: MonadIO m => Request -> m (Response ByteString)
httpJSON :: (MonadIO m, FromJSON a) => Request -> m (Response a )
请注意,httpLBS
始终会产生Response ByteString
,但httpLBS
会产生Response a
。这是什么意思?
在这种情况下,这意味着httpJSON
可以使用Response
实例生成包含任何内容的FromJSON
,并且由函数的调用者决定决定。来电者如何决定?通过指定类型!这是Haskell类型类中最有趣的属性之一:程序的行为由其类型决定。
当然,大多数时候,你没有看到那些类型,因为它们是推断的。例如,如果编写以下程序,则无需编写任何类型的注释:
ghci> id True
True
即使id
函数的类型为a -> a
,GHC也可以推断a
,Bool
只有一个选项,所以它被选中了。但是,考虑一下你的程序 - GHC如何知道a
应该是什么? response
结果仅用于一个地方getResponseStatusCode
,其中包含以下类型签名:
getResponseStatusCode :: Response a -> Int
此功能也适用于任何 Response a
,因此GHC仍然无法确定a
应该是什么:根据GHC的术语,a
变量含糊不清。问题是选择a
的特定类型是必要的,因为它需要知道用于解析响应主体的FromJSON
实例。
为了解决这个问题,您可以通过提供自己的类型注释来消除表达式的歧义,迫使GHC选择a
的特定类型:
makeRequest = do
response <- httpJSON "http://httpbin.org/get" :: IO (Response ())
putStrLn $ "The status code was: " ++ show (getResponseStatusCode response)
当然,您应该用代表您期望响应产生的JSON结构的任何类型替换()
。
答案 1 :(得分:0)
不确定这是否对其他人有帮助,但对我有帮助。我尝试使用::IO (Response ())
批注,然后返回完整的打印响应,然后返回"expected (), encountered Object"
,并将其切换为:: IO (Response Object)
使其固定为仅输出
λ makeRequest
200
it :: ()