我正在尝试构建一个简单的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。我没想到会改变一些事情,但谁知道......可能会提供线索。
答案 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