empty-list Travis Gitter Maven

The empty list collection.

The goal of this project is to open the discussion on the potential addition of an empty list collection to the standard library. This is a counter proposal to the idea of a non empty list that has been discussed repetitively for the collection strawman.

Try is out from sbt:

"in.nvilla" %% "empty-list" % "1.0" // use %%% for Scala.js

The empty list collection is defined as follows:

trait EmptyList[+T] extends Product with Serializable
final case object EmptyList extends EmptyList[Nothing]

The library also provides useful shorthands for the EmptyList type and value:

type EL[+T] = EmptyList[T]
val  EL     = EmptyList

A separate artifact with cats' type class instances for EmptyList is published as empty-list-cats.

The empty-list project and contributors support the Empty Code of Conduct and want all its associated channels (e.g. GitHub, Gitter) to be a safe and friendly environment for everyone.


How is EmptyList different from Nil?

  1. scala.collection.immutable.Nil defines unsafe operation such as head and tail. EmptyList doesn't. EmptyList is simply a better type to indicate emptiness!

    scala> Nil.head
    java.util.NoSuchElementException: head of empty list
      at scala.collection.immutable.Nil$.head(List.scala:428)
      ... 29 elided
    scala> Nil.tail
    java.lang.UnsupportedOperationException: tail of empty list
      at scala.collection.immutable.Nil$.tail(List.scala:430)
      ... 29 elided
  2. scala.collection.immutable.Nil loses it's emptiness type information as soon as it's used with any operation such as map of flatMap. Thanks to having it's own functor instance, EmptyList properly propagate type information!

    scala> Nil.map(identity)
    res1: List[Nothing] = List()
    scala> EL.map(identity)
    res2: EmptyList.type
  3. scala.collection.immutable.Nil has unhygienic equality, it can be compared to anything without scalac emitting any warning. Nil is also (surprisingly) equal to other empty collections that inherit scala.collection.GenSeq[_]:

    scala> Nil == Vector.empty
    res3: Boolean = true

    EmptyList is a proper algebraic data type, things always work as expected:

    scala> EL == Vector.empty
    <console>:1: warning: comparing values of types EL and Vector[Nothing] using `==` is always false
           EL == Vector.empty
    res4: Boolean = false