Haskell Wreq - не удалось сопоставить ожидаемый тип '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. Есть идеи, что здесь может происходить?

2 ответа

Решение

Ясно (компилятору, если не вашему собрату), что ("num" := (31337 :: Int)) :: FormParam. Что компилятору непонятно (и что вам нужно помочь ему решить), так это тип [x] однажды x известен как FormParam.

В Item "type" на самом деле является семейством типов, происходящим от класс; и 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] вместо этого имеет тип (GHC.Exts.IsList l, GHC.Exts.Item l ~ Bool) => l. После объединения print [True] в конечном итоге в основном имеет тип (Show a, GHC.Exts.IsList a, GHC.Exts.Item a ~ Bool) => IO (). Обратите внимание, что переменная типа нигде справа от =>, что делает этот тип неоднозначным. Чтобы сделать двусмысленность еще более конкретной, обратите внимание, что помимо [Bool], тип NonEmpty Bool также будет работать на aтам. Компилятор не знает, какой из них вы хотите, и не хочет угадывать, поэтому выдает эту ошибку. Чтобы решить проблему, добавьте аннотацию типа, например: main = print ([True] :: [Bool])

Для реальной проблемы в вашем вопросе единственное отличие состоит в том, что у вас есть Postable typeclass вместо Show, а FormParam тип вместо Bool. Вы можете решить свою проблему, заменив строку с ошибкой на res <- post "http://httpbin.org/post" (["num" := (31337 :: Int)] :: [FormParam]).

Другие вопросы по тегам