使用'=='时没有(Eq a0)的实例

时间:2014-07-09 22:05:01

标签: haskell

我是haskell的新手,我正试图解决这个问题http://www.haskell.org/haskellwiki/99_questions/1_to_10#Problem_7。为了验证结果,我使用Test.QuickCheck模块创建了一些测试。

    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 []) == [])

flatten实现是正确的,但是当我尝试运行此代码时,quickCheck函数出错了。

    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 []) == []) }

我知道我需要有一个Eq的实例来执行与(==)函数的比较,但我不知道如何实现它。有人能帮助我吗?

1 个答案:

答案 0 :(得分:3)

问题在于声明

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

这是因为您有List [],其类型为NestedList a,但您希望它为Eq a => NestedList a。尽管其中没有值,但当您使用==运算符时,它会强制该类型属于Eq类型类。围绕这个有两个简单的解决方法:

不是将列表与空列表进行比较,而是使用null,它具有实现

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

这就是我(以及hlint工具)建议做的事情。或者,您可以为其提供显式类型签名:

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

这里我使用()作为NestedList的类型参数,因为它的实现等同于

data () = ()

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

所以你不能真的出错。