I need to make a code that removes the first occurrence of an given element in a list. So far I have only managed to make the code remove every occurrence of the given element.
Her is my code rigth now:
rem2 :: Eq a => [a] -> a -> [a]
rem2 xs y = [x | x <- xs, x /= y]
If i try:
rem2 "hello" 'l'
The code will returne "heo", while I want it to returne "helo". Can someone help me?
CodePudding user response:
You can work with recursion here. If you reached the end of the list, then you return an empty list (1); if you are given a non-empty list (x:xs)
and the head of the list x
matched the item we are looking for (2), we return the tail of the list xs
; and in case the item does not match (3), we yield x
and recurse on the tail of the list xs
.
This function thus looks like:
rem1 :: Eq a => [a] -> a -> [a]
rem1 ls y = go ls
where go [] = … -- (1)
go (x:xs) | … = … -- (2)
| otherwise = … -- (3)
I leave implementing the …
parts as an exercise.
CodePudding user response:
Here's a simplified definition of delete
:
delete :: a -> [a] -> [a]
delete _ [] = []
delete x (y:ys) = if x == y then ys else y : delete x ys
It uses the more general function deleteBy
in the actual library. Here is the source code.
CodePudding user response:
Found a possibly solution, but not exactly what I wanted. The soulution is following:
import Data.List
rem1 :: Eq a => [a] -> a -> [a]
rem1 xs y = delete y xs
So if anyone have a solution which don't include a built-in function, I will gladly hear it from you.
CodePudding user response:
Here's a curiosity solution using list comprehensions as you wanted:
remfst :: Eq a => a -> [a] -> [a]
remfst a xs
| (j:_) <-
[ i | (x,i) <- zip xs [0..], i <- [i | x == a]]
= [ x | (x,i) <- zip xs [0..], x <- [x | i /= j]]
remfst _ xs = xs
Is it "disgusting"? In production code, sure. Here, it's just something to ponder about.
Now, we have
> remfst 'l' "helalo"
"healo"