解析主体代码中的内容使标题读取不会失败?

时间:2017-07-09 12:16:21

标签: haskell types

我正在尝试构建一个简单的Web scraper来从维基百科中获取一些文本语料库。我想使用他们的REST API在Haskell中构建一个简单的HTTP客户端。

为此,我转向了Network.HTTP.Simple包。在tutorial中,他们提供了以下代码段,我可以很好地运行。

#!/usr/bin/env stack
{- stack --install-ghc --resolver lts-5.13 runghc
    --package http-conduit
    --package yaml
-}
{-# LANGUAGE OverloadedStrings #-}
import           Data.Aeson            (Value)
import qualified Data.ByteString.Char8 as S8
import qualified Data.Yaml             as Yaml
import           Network.HTTP.Simple

main :: IO ()
main = do
    response <- httpJSON "http://httpbin.org/get"

    putStrLn $ "The status code was: " ++
               show (getResponseStatusCode response)
    print $ getResponseHeader "Content-Type" response
    S8.putStrLn $ Yaml.encode (getResponseBody response :: Value)

尝试理解我注释掉最后一行的代码(从S8.putStrLn开始......,现在代码中断了。错误是

No instance for (Yaml.FromJSON a0) arising from a use of ‘httpJSON’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance Yaml.FromJSON
                 aeson-1.2.1.0:Data.Aeson.Types.Internal.DotNetTime
        -- Defined in ‘aeson-1.2.1.0:Data.Aeson.Types.FromJSON’
      instance Yaml.FromJSON Value
        -- Defined in ‘aeson-1.2.1.0:Data.Aeson.Types.FromJSON’
      instance Yaml.FromJSON
                 attoparsec-0.13.1.0:Data.Attoparsec.Number.Number
        -- Defined in ‘aeson-1.2.1.0:Data.Aeson.Types.FromJSON’
      ...plus 78 others

所以我的问题是: (1)所以我的猜测是getResponseBody强制httpJSON的类型签名,所以解除了歧义。但是怎么样? (2)我可以在不调用getResponseBody的情况下消除歧义吗?我有什么选项来修复多态函数的返回类型?

编辑:我正在使用cabal run运行此操作,因为我没有安装Stack。我没想到会改变一些事情,但谁知道......可能会提供线索。

1 个答案:

答案 0 :(得分:2)

类型检查

我们有这个签名:getResponseBody :: Response a -> a

首先,在httpJSON之后,对于某些未知的response :: Response a0,我们有a0

然后我们写getResponseBody response,其类型为a0,但仍未知。

然后我们注释getResponseBody response :: Value,所以a0 ~ Value,现在实例解析有一个具体的类型可供使用。

限制response

类型的其他方法

您可以直接在response值使用的地方添加注释,例如,您可以在代码段的中间写getResponseStatusCode (response :: Response Value)

使用ScopedTypeVariables扩展名,您还可以注释绑定它的模式:(response :: Response Value) <- httpJSON "..."

a0类型变量也出现在httpJSON的结果类型中,因此您也可以对其进行注释。

response <- httpJSON "..." :: IO (Response Value)

使用TypeApplications,这里有更多选择,任何一个应该足以让类型检查器推断出a0 ~ Value

response <- httpJSON @_ @Value "..."

getResponseStatusCode @Value response
getResponseHeader @Value "..." response
getResponseBody @Value response