I am new in this comunity. I learn Haskell and have difficulties with Haskell-coding. I hope you can help me.
I searched here and in Google, without any success.
My problem ist as fowllows: I want to write a function which takes a list as parameter like this:
myStringListFilter :: [String] -> [String]
process the following steps:
Remove the first letter
myStringListFilter myList = map tail strListe myList
Filter every element in the list which begins with "u" or "U".
myStringListFilter myList = filter (´elem´ ['u', 'U']) (map tail strListe myList)
Step two doesn't work. I get error.
How do I achieve the solution, if I want the following:
Input: ["butter", "chees", "aUbergine", "egg", "milk", "bUbble", "curry"]
Output: ["chees", "egg", "milk"]
The type of filter
is
filter :: (a -> Bool) -> [a] -> [a]
so if you want to filter a list of String
s according to a predicate, you need a function String -> Bool
, but what you wrote, (`elem` ['u',U'])
has type Char -> Bool
.
So you need a function
beginsWithU :: String -> Bool
the easiest way to define it is
beginsWithU (c:_) = c == 'u' || c == 'U'
beginsWithU _ = False -- empty list
Then you have misunderstood how filter
works, it keeps the elements satisfying the predicate, you want to remove them, so you need to compose the predicate with a not
(or define as doesn'tbeginWithU
directly).
However, as 7stud points out, you do not actually want to change the elements you want to keep from the original list, what
myStringListFilter myList = filter (not . beginsWithU) (map tail myList)
or, point-free:
myStringListFilter = filter (not . beginsWithU) . map tail
would achieve. So you need to incorporate the tail
into the predicate too, and need no map
, that would yield
myStringListFilter = filter (not . beginsWithU . tail)
or, if the possibility that an empty String
occurs in the input list shall be dealt with benignly,
myStringListFilter = filter (not . beginsWith . drop 1)
since tail ""
would produce an *** Exception: Prelude.tail: empty list
whereas drop 1 ""
produces ""
.
But, as you want to keep the original list element, you can also define the predicate to directly look at the second character,
secondCharIsU :: String -> Bool
secondCharIsU (_:c:_) = c == 'u' || c == 'U'
secondCharIsU _ = False
myStringListFilter = filter (not . secondCharIsU)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With