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.