简体   繁体   中英

No instance for (Eq a0) arising from a use of ‘==’

I'm new to haskell and I'm trying to solve this haskell problem http://www.haskell.org/haskellwiki/99_questions/1_to_10#Problem_7 . To verify the result I created some tests using Test.QuickCheck module.

    import Test.QuickCheck
    import Test.QuickCheck.All

    {- ------------- -}
    {- SOLUTION      -}
    {- ------------- -}

    data NestedList a = Elem a | List [NestedList a]

    flatten :: NestedList a -> [a]
    flatten (Elem x) = [x]
    flatten (List x) = concatMap flatten x

    {- ------------- -}
    {- TEST CASE     -}
    {- ------------- -}

    main = do
        quickCheck (flatten (Elem 5) == [5])
        quickCheck (flatten (List [Elem 1, List [Elem 2, List [Elem 3, Elem 4], Elem 5]]) == [1,2,3,4,5])
        quickCheck (flatten (List []) == [])

The flatten implementation is correct but, when I try to run this code I have an error with the quickCheck functions.

    Problem7.hs:43:39:
        No instance for (Eq a0) arising from a use of ‘==’
        The type variable ‘a0’ is ambiguous
        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 114 others
        In the first argument of ‘quickCheck’, namely
          ‘(flatten (List []) == [])’
        In a stmt of a 'do' block: quickCheck (flatten (List []) == [])
        In the expression:
          do { quickCheck (flatten (Elem 5) == [5]);
               quickCheck (flatten (List [Elem 1, List [...]]) == [1, 2, ....]);
               quickCheck (flatten (List []) == []) }

I know that I need to have an instance of Eq to perform the comparisons with (==) function, but I don't know how to implement it. Can someone help me?

The problem is with the statement

quickCheck (flatten (List []) == [])

and it's because you have List [] , which has type NestedList a , but you want it to be Eq a => NestedList a . Even though there are no values in it, when you use the == operator it enforces that the type belong to the Eq typeclass. There are two simple fixes around this:

Instead of comparing a list against the empty list, use null , which has the implementation

null :: [a] -> Bool
null [] = True
null _ = False

This is what I (and the hlint tool) would suggest doing. Alternatively, you can provide it with an explicit type signature:

quickCheck (flatten (List [] :: NestedList ()) == [])

Here I've used () as the type parameter to NestedList , since its implementation is equivalent to

data () = ()

instance Eq () where
    () == () = True

So you can't really go wrong with it.

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