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 a
s, 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