我是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
的实例来执行与(==)函数的比较,但我不知道如何实现它。有人能帮助我吗?
答案 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
所以你不能真的出错。