Haskell Wreq - 无法匹配预期类型“GHC.Exts.Item a0”

Haskell Wreq - Couldn't match expected type ‘GHC.Exts.Item a0’

我在 运行 以下代码时遇到类型错误:

runPost :: IO String
runPost = do
    res <- post "http://httpbin.org/post" ["num" := (31337 :: Int)]
    return $ show res

错误如下:

• Couldn't match expected type ‘GHC.Exts.Item a0’
                  with actual type ‘FormParam’
      The type variable ‘a0’ is ambiguous
    • In the expression: "num" := (31337 :: Int)
      In the second argument of ‘post’, namely
        ‘["num" := (31337 :: Int)]’
      In a stmt of a 'do' block:
        res <- post "http://httpbin.org/post" ["num" := (31337 :: Int)]

当我在 ghci 中检查 := 的类型时,我看到什么似乎是正确的类型:

*Main Network.Wreq> :t (:=)
(:=)
  :: FormValue v =>
     Data.ByteString.Internal.ByteString -> v -> FormParam

我想知道的是,当我 运行 编译器时,为什么 GHC.Exts.Item 显示为预期类型。我只从 Network.Wreq 导入了我正在使用的函数。知道这里会发生什么吗?

("num" := (31337 :: Int)) :: FormParam 很清楚(对编译器而言,如果不是对你的人类同胞而言)。一旦 x 被认为是 FormParam.

,编译器不清楚的(以及您需要帮助它决定的)是 [x] 的类型

Item“类型”实际上是一个类型家族,来自IsListclass;并且 IsList 连接来自 OverloadedLists 扩展打开。

这是一个导致基本相同错误的最小程序,它应该更清楚发生了什么:

{-# LANGUAGE OverloadedLists #-}

main :: IO ()
main = print [True]
    • Couldn't match expected type ‘GHC.Exts.Item a0’
                  with actual type ‘Bool’
      The type variable ‘a0’ is ambiguous
    • In the expression: True
      In the first argument of ‘print’, namely ‘[True]’
      In the expression: print [True]
  |
4 | main = print [True]
  |               ^^^^

print 函数的类型为 Show a => a -> IO ()。如果未启用 OverloadedLists 扩展,那么表达式 [True] 的类型将是 [Bool],一切都会好起来的。但是启用 OverloadedLists 扩展后,表达式 [True] 的类型改为 (GHC.Exts.IsList l, GHC.Exts.Item l ~ Bool) => l。统一后,print [True] 基本上变成了 (Show a, GHC.Exts.IsList a, GHC.Exts.Item a ~ Bool) => IO () 类型。请注意,类型变量 a 没有出现在 => 右侧的任何位置,这使得它成为一个不明确的类型。为了使歧义更加具体,请注意,除了 [Bool] 之外,类型 NonEmpty Bool 也适用于 a。编译器不知道你想要哪一个,也不想猜测,所以它给了你那个错误。为了解决这个问题,添加一个类型注释,像这样:main = print ([True] :: [Bool])

对于您问题中的实际问题,唯一的区别是您使用 Postable 类型类而不是 Show,并且使用 FormParam 类型而不是 Bool .您可以通过将错误行替换为 res <- post "http://httpbin.org/post" (["num" := (31337 :: Int)] :: [FormParam]).

来解决您的问题