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

烈酒焚心 提交于 2019-12-24 10:38:46

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/24664501/no-instance-for-eq-a0-arising-from-a-use-of

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!