null

A predicate that tells you whether something is empty is conventionally named null.

You can find the following function in the Prelude module:null in Prelude

null :: Foldable t => t a -> Bool

What things are Foldable?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 [Char], so null can also tell you whether a string is the empty string.

λ> filter (not . null) ["one", "", "two", "", ""]
["one","two"]

The expression 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 xs
False

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 Foldable instances,Set, Map, HashSet, HashMap, Vector not just lists. So null also works with Set, Map, HashSet, HashMap, 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:

Data.Set.null          :: Set a       -> Bool
Data.Map.Lazy.null     :: Map k a     -> Bool
Data.HashSet.null      :: HashSet a   -> Bool
Data.HashMap.Lazy.null :: HashMap k a -> Bool
Data.Vector.null       :: Vector a    -> Bool

There are some typesText, ByteString like Text and 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.A Word8 is a byte. These modules too define their own functions called null that follow this pattern.

Data.Text.null       :: Text       -> Bool
Data.ByteString.null :: ByteString -> Bool

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 oneMonoFoldable 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 onull.

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

The ListLike packageListLike 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 Foldable and 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

Join Type Classes for courses and projects to get you started and make you an expert in FP with Haskell.