简体   繁体   中英

Haskell error “No instance for (Eq a0) arising from a use of…”

Anyone knows why the following code fails in " matchListWith eq [] [] "?

-- failure.hs

matchListWith :: (Eq a) => (a -> a -> Bool) -> [a] -> [a] -> Bool
matchListWith f (x:xs) (y:ys) = (f x y) && (matchListWith f xs ys)
matchListWith _ []     []     = True
matchListWith _ _      _      = False

eq :: (Eq a) => a -> a -> Bool
eq a b = (a == b)

main = do
   print (matchListWith eq [1, 3] [1, 3])
   print (matchListWith eq [1, 3] [1])
   print (matchListWith eq [1] [1, 3])
   print (matchListWith eq [3, 1] [1, 3])
   print (matchListWith eq [1] [])
   print (matchListWith eq [] [])

-- eof

The error is:

failure.hs:16:11:
    No instance for (Eq a0) arising from a use of `matchListWith'
    The type variable `a0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Eq a => Eq (GHC.Real.Ratio a) -- Defined in `GHC.Real'
      instance Eq () -- Defined in `GHC.Classes'
      instance (Eq a, Eq b) => Eq (a, b) -- Defined in `GHC.Classes'
      ...plus 22 others
    In the first argument of `print', namely `(matchListWith eq [] [])'
    In a stmt of a 'do' block: print (matchListWith eq [] [])
    In the expression:
      do { print (matchListWith eq [1, 3] [1, 3]);
           print (matchListWith eq [1, 3] [1]);
           print (matchListWith eq [1] [1, 3]);
           print (matchListWith eq [3, 1] [1, 3]);
           .... }

The weird things is, if I load the two functions in GHCi, matchListWith eq [] [] , works just fine.

*Main> matchListWith eq [] []
True
*Main> 

I'm using GHC version 7.6.3.

The reason is because when you call

matchListWith eq [] []

The compiler doesn't know what type of list it is. All it knows is that it's a value of type [a] , but that does not put the Eq a => constraint on it. Change it to

matchListWith eq [] ([] :: [Int])

and it should compile


Sometimes you have to give GHC a bit of help to know what types it's working with. It would be the same if you tried

myFunc :: m Int
myFunc = do
    let x = 1
        y = 2
    return $ x + y

This wouldn't compile because the compiler isn't told that m is a Monad , you have to add the extra context of

myFunc :: Monad m => m Int

for it to work.

The reason why it works in GHCi is because there's a bit more eager type inference. GHCi will often pick a more concrete type than GHC will in order to make the interactive part easier to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM