Haskell: Stuck writing a function to replicate`elem`
For my very first lecture in haskell we where given a series of problems. One of them is to return True when n number is present in a list, or False otherwise. I managed to get what i think is half-way there but am getting different compile errors and am pretty frustated because I can even understand what they mean.
So far I have done the following
// No problem with this function
matches :: Int -> [Int] -> [Int] // This function is to return the matches
matches x y = [a | a <-y, a==x] // ie. main> 1 [1,3,5,7,1,4] outputs [1,1]
// Here am stuck
myelem :: Int -> [Int] -> Bool
myelem x [] = False
myelem x (y:ys)
| x == y = y : x myelem ys // Am not sure about recursion as
// we have not yet covered
Obviously this is for a class so please do not post the answer. But maybe a few examples that will help me reason about both the workings of Has开发者_JAVA技巧kell and how to approach the problem. Any pointer will be massively appreciated.
SOLUTION
matches :: Int -> [Int] -> [Int]
matches x y = [a | a <-y, a==x]
myelem :: Int -> [Int] -> Bool
myelem x [] = False
myelem x (y:ys)
| x == y = True
| otherwise = myelem x (ys)
Cheers guys
The problem is in your last equation:
myelem x (y:ys)
| x == y = y : x myelem ys
There are two problems here:
If you want to use
myelem
as an infix operator, you have to surround it in backticks, like so:x `myelem` ys
Given that's what you meant, the right hand side of your equation doesn't type check; the list constructor
(:)
requires its second argument to be a list, not aBool
. Furthermore,(:)
constructs a list, andmyelem
is supposed to return aBool
!
Think about what you're trying to do. If x == y
, you just want to return True
, right? And otherwise
, you want to return the result of checking the rest of the list (ys
). Hope that helps.
You are actually pretty close to the right answer. I see two main issues, though. One is that the call to myelem
on the last line of code needs to have backquotes around it to make it infix (x `myelem` ys
) or a prefix call without backquotes (myelem x ys
). Also, you do not want to prepend y
to the result of the recursive call. You actually do not need a condition on your second pattern: just think about what myelem x (y:ys)
should return using simple Boolean operations and the recursive call you already have there.
You try to concat an Int
and a Bool
in the last line; think again.
You never return True
from myelem
; sometimes it is appropriate.
Once these issues are fixed, the code works.
You could also write your function using some combination of the following functions (there are at least two ways of doing it using the functions below):
filter :: (a -> Bool) -> [a] -> [a]
removes elements from a list unless they satisfy some set of criteria
null :: [a] -> Bool
returns whether the list is empty or not
not :: Bool -> Bool
is logical negation
or :: [Bool] -> Bool
returns True if a list of Bool contains one or more True values.
Obviously, you've solved your problem, but it might help you to explore other ways of doing the same thing.
Note that you could also define your myelem
function in terms of matches
.
- What will matches return if the item is not in the list?
- What will matches return if the item is in the list once? twice? many times?
- Do you care about the entire return value in the second case? (hint: no)
精彩评论