2

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

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. 有什么想法可能会在这里发生吗?

4

2 回答 2

3

很明显(对编译器来说,如果不是对你的同胞来说)("num" := (31337 :: Int)) :: FormParam. 编译器不清楚的是(您需要帮助它做出决定)的类型[x]x已知的FormParam.

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

于 2021-10-12T02:51:19.793 回答
1

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

{-# 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]将具有 type [Bool],一切都会好起来的。但是OverloadedLists启用扩展后,表达式[True]改为具有 type (GHC.Exts.IsList l, GHC.Exts.Item l ~ Bool) => l。统一之后,print [True]基本上就有了 type 了(Show a, GHC.Exts.IsList a, GHC.Exts.Item a ~ Bool) => IO ()。请注意,类型变量a不会出现在 右侧的任何地方=>,这使得它成为一种模棱两可的类型。为了使歧义更加具体,请注意,除了 之外[Bool],该类型NonEmpty Bool也适用于a那里。编译器不知道你想要哪个,也不想猜测,所以它会给你那个错误。要解决此问题,请添加类型注释,如下所示:main = print ([True] :: [Bool])

对于您问题中的实际问题,唯一的区别是您有Postabletypeclass 而不是Show,而FormParamtype 不是Bool. 您可以通过将错误行替换为 来解决您的问题res <- post "http://httpbin.org/post" (["num" := (31337 :: Int)] :: [FormParam])

于 2021-10-12T17:33:54.350 回答