Suppose I have the data type
data Joke = Funny String | Lame String
and say I have the following nested list
[[Funny \"Hah
As a preliminary step, let's derive Eq
and Show
instances for your type:
data Joke = Funny String | Lame String
deriving (Eq, Show)
Eq
makes it possible to test the (in)equality of Joke
s, while Show
makes it possible to display the results of your tests in GHCi.
filter is the right tool here:
excludeHaha :: [[Joke]] -> [[Joke]]
excludeHaha = filter (notElem (Funny "Haha"))
This filters the (outer) list so that only inner lists with all elements different from Funny "Haha"
are kept.
Trying it out:
GHCi> excludeHaha [[Funny "Haha", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Lame "BOO"]]
If you don't want to hardcode "Haha"
, add a parameter and pass it on to the test:
excludeAFunnyJoke :: String -> [[Joke]] -> [[Joke]]
excludeAFunnyJoke s = filter (notElem (Funny s))
GHCi> excludeAFunnyJoke "LOL" [[Funny "LOL", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Funny "Haha"],[Lame "BOO"]]
If you wanted instead to exclude all Funny
jokes, regardless of what the contained String
is, you could use pattern matching to define an appropriate test:
excludeFunny :: [[Joke]] -> [[Joke]]
excludeFunny = filter (all (not . isFunny))
where
isFunny :: Joke -> Bool
isFunny joke = case joke of
Funny _ -> True
_ -> False
The filtering test here uses all, which applies its own test (here, (/= Funny "Haha")
) to the elements of the (inner) list and then folds the resulting [Bool]
with (&&)
.
(You might as well define isLame
and use it instead of not . isFunny
-- note, though, that that would only work because you happen to have just two constructors.)
GHCi> excludeFunny [[Funny "LOL", Lame "boo"], [Funny "Haha"], [Lame "BOO"]]
[[Lame "BOO"]]
P.S.: A manual implementation of the Eq
instance would look like this:
instance Eq Joke where
Funny x == Funny y = x == y
Lame x == Lame y = x == y
Funny _ == Lame _ = False
Lame _ == Funny _ = False
You might replace the last two cases by a catch-all (_ == _ = False
), saving one line at the cost of making it a little easier to forget updating the instance if you ever add more constructors to Joke
. In any case, such definitions are boring busywork, so we avoid it with deriving
unless there is a need for a non-obvious equality test.