I'm experiencing a type error when I run the following code:
runPost :: IO String
runPost = do
res <- post "http://httpbin.org/post" ["num" := (31337 :: Int)]
return $ show res
The error is the following:
• 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)]
When I inspect the type of :=
in ghci, I see what appears to be the correct type:
*Main Network.Wreq> :t (:=)
(:=)
:: FormValue v =>
Data.ByteString.Internal.ByteString -> v -> FormParam
What I'm wondering is why GHC.Exts.Item
is appearing as the expect type when I run the compiler. I've only imported the functions I'm using from Network.Wreq
. Any ideas what might be going on here?
CodePudding user response:
It's clear (to the compiler, if not to your fellow human) that ("num" := (31337 :: Int)) :: FormParam
. What isn't clear to the compiler (and which you need to help it decide on) is the type of [x]
once x
is known to be a FormParam
.
The Item
"type" is actually a type family, coming from the IsList
class; and the IsList
connection is coming from having the OverloadedLists
extension turned on.
CodePudding user response:
Here's a minimal program that causes basically the same error, which should make it more clear what's going on:
{-# 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]
| ^^^^
The print
function has type Show a => a -> IO ()
. If the OverloadedLists
extension weren't enabled, then the expression [True]
would have type [Bool]
, and everything would be fine. But with the OverloadedLists
extension enabled, the expression [True]
instead has type (GHC.Exts.IsList l, GHC.Exts.Item l ~ Bool) => l
. After unifying, print [True]
ends up basically having type (Show a, GHC.Exts.IsList a, GHC.Exts.Item a ~ Bool) => IO ()
. Notice that the type variable a
doesn't appear anywhere to the right of the =>
, which makes that an ambiguous type. To make the ambiguity even more concrete, note that in addition to [Bool]
, the type NonEmpty Bool
would also work for a
there. The compiler doesn't know which one you want and doesn't want to guess, so it gives you that error. To solve the problem, add a type annotation, like this: main = print ([True] :: [Bool])
For the actual problem in your question, the only differences are that you have the Postable
typeclass instead of Show
, and the FormParam
type instead of Bool
. You can fix your problem by replacing the erroring line with res <- post "http://httpbin.org/post" (["num" := (31337 :: Int)] :: [FormParam])
.