繁体   English   中英

为什么httpJSON失败,但httpLBS成功了?

[英]Why does httpJSON fail, but httpLBS succeeds?

此功能(使用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.

比较httpLBShttpJSON的类型:

httpLBS ::   MonadIO m              => Request -> m (Response ByteString)
httpJSON :: (MonadIO m, FromJSON a) => Request -> m (Response a         )

请注意, httpLBS 始终生成Response ByteString ,但httpLBS生成Response a 这意味着什么?

在这种情况下,这意味着httpJSON可以使用FromJSON实例生成包含任何内容的Response ,并且由函数的调用者决定。 来电者如何决定? 通过指定类型! 这是Haskell的类型类中最有趣的属性之一:程序的行为由其类型决定。

当然,大多数时候,你没有看到那些类型,因为它们是推断的。 例如,如果编写以下程序,则无需编写任何类型的注释:

ghci> id True
True

即使id函数具有类型a -> a ,GHC也可以推断出aBool只有一个选择,所以选择它。 然而,考虑你的程序如何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结构的类型替换()

不确定这是否对其他人有帮助,但它帮助了我。 我尝试了::IO (Response ())注释,我得到了完整的打印响应然后"expected (), encountered Object" ,并将其切换到:: IO (Response Object)修复它只是输出

λ makeRequest
200
it :: ()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM