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

标签 haskell http-conduit

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

最佳答案

比较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 结构。

关于haskell - 为什么 httpJSON 失败,但 httpLBS 成功?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46694290/

相关文章:

windows - Windows 8 上的 "InternalIOException getAddrInfo: does not exist (error 10093)"

http - 增加 Network.HTTP.Conduit 的请求超时

haskell - 将类型 `t` 上的运算符转换为类型 `a->t` 上的运算符

haskell - 在堆栈中运行测试套件的惯用方式

haskell - Reader monad - reader vs asks 功能区别?

haskell - 将 http-conduit 连接到 xml-conduit

haskell - 当我并行运行大量 http 请求时,我得到 "no such protocol name: tcp"

haskell - 应该将列表转换为字符串的函数中的解析错误 - haskell

haskell - 无法将多个客户端与 Haskell Websocket 服务器一起使用

haskell - 使用 Scotty 的网络 I/O 吞吐量出乎意料地低