elem
Next is the elem function
elem :: Eq a => a -> t a -> Bool
which we already discussed for lists. It checks whether a given element is part of the container:
>>> 3 `elem` [1,2,3]
True
>>> 4 `elem` [1,2,3]
False
Given an element of type a and a collection of as, it decides whether
the element is in the collection. To perform this test, we need a to
support equality testing. Thus, we need the Eq a type constraint.
The default implementation of elem uses any, which is a function that is not
part of the Foldable class but is supported by all foldable containers. We'll
discuss it at the end of this chapter, along with a few other useful functions
for foldable containers.
For now, it suffices to know that any pred xs is True if and only if
there exists an element in xs for which the predicate pred is true. This
gives the following type signature for any:
any :: Foldable t => (a -> Bool) -> t a -> Bool
Using this function, elem can be implemented as
elem = any . (==)
Again, this may be a bit terse, but it is useful to get used to defining functions via function composition. Let's once again use equational reasoning to figure out that this is the correct implementation. What we want is that
y `elem` xs = any (\x -> y == x) xs
We want to test every element x in xs whether it is equal to y, and we
want to return True if there exists at least one element that is equal to
y. Here's how we obtain the definition elem = any . (==) from this more
verbose definition:
y `elem` xs = any (\x -> y == x) xs -- Definition of `elem`
elem y xs = any (\x -> y == x) xs -- Convert to using elem in prefix notatation
elem y = any (\x -> y == x) -- Drop the common argument xs
elem y = any (\x -> (==) y x) -- Convert to using (==) in prefix notation
elem y = any ((==) y) -- (\x -> (==) y x) applies ((==) y) to x,
-- so (\x -> (==) y x) is the same as ((==) y)
elem y = (any . (==)) y -- Definition of function composition
elem = any . (==) -- Drop the common argument y
Once again, elem doesn't work only for lists (using the same tree we have
used previously):
>>> 1 `elem` Nothing
False
>>> 1 `elem` Just 1
True
>>> 1 `elem` Just 2
False
>>> 5 `elem` tree
True
>>> 5 `elem` Empty
False
>>> 4 `elem` tree
False