A predicate that tells you whether something is empty is conventionally named
You can find the following function in the
null :: Foldable t => t a -> Bool
What things are
Foldable One example is lists.
null can tell you whether a list is empty.
λ> null  True λ> null [1,2,3]False
String is a type alias for
null can also tell you whether a string is the empty string.
λ> filter (not . null) ["one", "", "two", "", ""]["one","two"]
null xs is usually equivalent to
length xs == 0. But
null may be much faster. Consider what happens if the list is quite large;
length must evaluate the entire list, so it takes a while. But
null doesn’t need to go any further than the first element to figure out that a list is not empty.
λ> xs = [1..100000000] λ> length xs == 0 False λ> null xsFalse
Remember also that lists can be infinite, which means that the
length approach may not even work at all.
null will, though.
λ> xs = cycle [1,2,3] λ> null xs False λ> length xs == 0-- doesn't terminate, don't try this at home
Plenty of other “collection”-like types have
Vector not just lists. So
null also works with
Vector, etc. All of these modules also define their own
null functions, so you can use a less-polymorphic version instead of the method from
Foldable if you like:
:: Set a -> Bool Data.Set.null :: Map k a -> Bool Data.Map.Lazy.null :: HashSet a -> Bool Data.HashSet.null :: HashMap k a -> Bool Data.HashMap.Lazy.null :: Vector a -> BoolData.Vector.null
There are some types
ByteString that aren’t “collections” in this sense, because they don’t have a type parameter, but are still sort of list-like.
Text is conceptually a list of characters, and
ByteString is conceptually a list of
Word8 is a byte. These modules too define their own functions called
null that follow this pattern.
:: Text -> Bool Data.Text.null :: ByteString -> BoolData.ByteString.null
There are a few classes outside of
base that generalize these kinds of parameterless collections.
Whereas collections whose element type is parameterized belong to the
Foldable class, collections that only work with one
MonoFoldable is defined in the
mono-traversable package. specific type of element belong to the
MonoFoldable class. A type family called
Element specifies what kind of elements each of these collections holds. The functions in the
mono-traversable package are all prefixed with the letter
o to distinguish them from similar-named things in
Prelude, so the emptiness test in
MonoFoldable is called
class MonoFoldable mono where onull :: mono -> Bool -- ... and many other methods... type family Element mono type instance Element ByteString = Word8 type instance Element Text = Char
λ> import Data.MonoTraversable λ> Data.MonoTraversable.onull (Data.Text.pack "") True λ> Data.MonoTraversable.onull (Data.Text.pack "abc")False
ListLike is the name of both the class and the package. also defines a class with a
null method. It takes a different approach to handling monomorphic collections, using a multi-parameter typeclass instead of a type family. The
ListLike class is more specific than
MonoFoldable; it only pertains to things that have a linear structure, like lists and
Vectors. Types like
Map are not list-like in this way. The
ListLike documentation points out that technically
Map could have a
ListLike instance, but it behaves oddly.
class (FoldableLL full item, Monoid full) => ListLike full item | full -> item where null :: full -> Bool -- ... and many other methods...
λ> import Data.ListLike λ> Data.ListLike.null (Data.Text.pack "") True λ> Data.ListLike.null (Data.Text.pack "abc")False