list-singleton-2.0.0.2: Easily and clearly create lists with only one element in them.
Safe HaskellSafe-Inferred
LanguageHaskell2010

Data.List.Singleton

Description

This module is meant to augment the Data.List module. You may want to import both modules using the same alias. For example:

import qualified Data.List as List
import qualified Data.List.Singleton as List
Synopsis

Documentation

singleton :: a -> [a] Source #

O(1) Create a list with a single element in it.

>>> singleton "pepperoni"
["pepperoni"]

There are many other ways to construct lists, so why might you prefer to use singleton? Here's a comparison with a few popular methods:

  • If you already have the element as a named value like x, you can wrap it up in a list literal: [x]. You should prefer doing that to calling singleton.

    -- Instead of this:
    singleton x
    
    -- Consider this instead:
    [x]
    
  • If you don't already have the element named, you can introduce a name by using a lambda: (\ x -> [x]). This is perhaps the most common way to create a singleton list, but it focuses more on mechanics than intent. Also it can be get little noisy, especially with identifiers longer than single letters like x.

    -- Instead of this:
    g . (\ x -> [x]) . f
    
    -- Consider this instead:
    g . singleton . f
    
  • If you don't want to introduce a name at all, you can use an operator section: (: []). This is more advanced because it requires familiarity with operator sections, list constructors, and how lists are desugared. (If you're not familiar with those concepts, the expression (: []) is the same as (\ x -> x : []), which is the same as (\ x -> [x]).) While those concepts are perhaps fundamental to understanding Haskell, you can get surprisingly far without them.

    -- Instead of this:
    g . (: []) . f
    
    -- Consider this instead:
    g . singleton . f
    
  • If you want to avoid lambdas, lists, and operators completely, you can use the pure method from the Applicative type class. This has a lot of upsides: it's short, it's in the Prelude, and it's easy to search for. Unfortunately it has one downside: it's polymorphic. That means it can return any type that has an Applicative instance, like Maybe or IO. By comparison singleton is monomorphic and can only produce a list. Usually the fact that pure is polymorphic isn't a problem, but sometimes it can produce confusing errors. Using singleton can be a good way to force polymorphic code to use a list.

    >>> import Data.Char (chr)
    >>> print (pure (chr 72))
    ...
    <interactive>:2:8: error:
        * Ambiguous type variable `f0' arising from a use of `pure'
          prevents the constraint `(Applicative f0)' from being solved.
          Probable fix: use a type annotation to specify what `f0' should be.
    ...
    >>> print (singleton (chr 72))
    "H"
    
    -- Instead of this:
    g . pure . f
    
    -- Consider this instead:
    g . singleton . f
    

Now that you've seen a bunch of ways to create singleton lists, you may be wondering why you'd want to do that at all. It's not often that you'll want to make a list with one element in it and call it a day. Usually it's part of a bigger computation. An illustrative example is the foldMap function, which can allow you to create a large data structure (like an entire list) by stitching together a bunch of tiny lists. This can be an effective way to convert between data types. For example:

>>> import qualified Data.List.Singleton as List
>>> import qualified Data.Set as Set
>>> let aList = [2, 1, 3, 1]
>>> foldMap Set.singleton aList
fromList [1, 2, 3]
>>> let aSet = Set.fromList [2, 3, 1]
>>> foldMap List.singleton aSet
[1, 2, 3]

The name "singleton" was chosen to mirror similar functions provided by other libraries. For example:

Note that singleton is lazy in its argument.

>>> length (singleton undefined)
1

If you want to create a NonEmpty list with a single element in it, consider using singleton from Data.List.NonEmpty.Singleton.

Since: 1.0.0.0