Reputation: 3443
I roll my own elem
function called elem'
elem' :: (Eq a) => a -> [a] -> Bool
elem' n ys = foldl (\acc p -> if (p == n) then True else False) False ys
Seems to work but I want to quickCheck it in GHCi so I import Test.QuickCheck
verboseCheck (\a -> (\xs ->( (elem' a xs) == (elem a xs)) ) )
Without a type declaration on the test function it tests ok, but that's because it's only testing null inputs.
Something is wrong with my type declaration for the test function:
verboseCheck (\a->(\xs->((elem' a xs)==(elem a xs))) :: Int->[Int]->Bool)
verboseCheck (\a->(\xs->((elem' a xs)==(elem a xs))) :: Char->[Char]->Bool)
Error for first one:
• Couldn't match expected type ‘[Int] -> Bool’
with actual type ‘Bool’
• Possible cause: ‘(==)’ is applied to too many arguments
In the expression: ((elem' a xs) == (elem a xs))
In the expression:
(\ xs -> ((elem' a xs) == (elem a xs))) :: Int -> [Int] -> Bool
In the first argument of ‘verboseCheck’, namely
‘(\ a
-> (\ xs -> ((elem' a xs) == (elem a xs))) ::
Int -> [Int] -> Bool)’
<interactive>:258:39: error:
• Couldn't match expected type ‘[()]’ with actual type ‘Int’
• In the second argument of ‘elem'’, namely ‘xs’
In the first argument of ‘(==)’, namely ‘(elem' a xs)’
In the expression: ((elem' a xs) == (elem a xs))
<interactive>:258:54: error:
• Couldn't match expected type ‘[()]’ with actual type ‘Int’
• In the second argument of ‘elem’, namely ‘xs’
In the second argument of ‘(==)’, namely ‘(elem a xs)’
In the expression: ((elem' a xs) == (elem a xs))
Upvotes: 3
Views: 117
Reputation: 233135
This happens because Haskell thinks that you're constraining the return type of the lambda expression \a->(\xs->((elem' a xs)==(elem a xs)))
. This may be easier to see if you format the expression a bit more idiomatically:
\a -> (\xs -> ((elem' a xs) == (elem a xs)))
To the interpreter/compiler, this looks like a lambda expression that returns another expression. All good.
However, when you attempt to annotate it with a type:
\a -> (\xs -> ((elem' a xs) == (elem a xs))) :: Int -> [Int] -> Bool
Haskell thinks that you're annotating the return type, i.e. the right-most part closest associated with the type annotation: (\xs -> ((elem' a xs) == (elem a xs)))
.
Surround the entire lambda expression with brackets before applying the type:
(\a -> (\xs -> ((elem' a xs) == (elem a xs)))) :: Int -> [Int] -> Bool
You can now verboseCheck
that expression:
Prelude Test.QuickCheck> verboseCheck ((\a -> (\xs -> ((elem' a xs) == (elem a xs)))) :: Int -> [Int] -> Bool)
Passed:
0
[]
Passed:
0
[]
Passed:
0
[-2,0]
Failed:
1
[2,1,-1]
Passed:
0
[2,1,-1]
Passed:
1
[]
Failed:
1
[1,-1]
Passed:
0
[1,-1]
Passed:
1
[]
Passed:
1
[-1]
Passed:
1
[1]
Passed:
1
[0,-1]
Passed:
1
[1,1]
Failed:
1
[1,0]
Passed:
0
[1,0]
Passed:
1
[]
Passed:
1
[0]
Passed:
1
[1]
Passed:
1
[0,0]
*** Failed! Falsified (after 4 tests and 2 shrinks):
1
[1,0]
Most of the brackets, however, are redundant, which is probably what's causing the confusion. You can simplify the expressions to this:
verboseCheck ((\a xs -> elem' a xs == elem a xs) :: Int -> [Int] -> Bool)
verboseCheck ((\a xs -> elem' a xs == elem a xs) :: Char -> [Char] -> Bool)
Upvotes: 5