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

Time:10-13

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 typeGHC.Exts.Item a0’
                  with actual typeFormParam
      The type variable ‘a0’ is ambiguousIn 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 typeGHC.Exts.Item a0’
                  with actual typeBool
      The type variable ‘a0’ is ambiguousIn 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]).

  • Related