arrow-core-data / arrow.core / NonEmptyList

NonEmptyList

@higherkind class NonEmptyList<out A>

beginner

NonEmptyList is a data type used in Λrrow to model ordered lists that guarantee to have at least one value. NonEmptyList is available in the arrow-core-data module under the import arrow.core.NonEmptyList

of

A NonEmptyList guarantees the list always has at least 1 element.


import arrow.core.NonEmptyList

val value =
//sampleStart
 // NonEmptyList.of() // does not compile
 NonEmptyList.of(1, 2, 3, 4, 5) // NonEmptyList<Int>
//sampleEnd
fun main() {
 println(value)
}

Unlike List[0], NonEmptyList.head it’s a safe operation that guarantees no exception throwing.


import arrow.core.NonEmptyList

val value =
//sampleStart
 NonEmptyList.of(1, 2, 3, 4, 5).head
//sampleEnd
fun main() {
 println(value)
}

foldLeft

When we fold over a NonEmptyList, we turn a NonEmptyList< A > into B by providing a seed value and a function that carries the state on each iteration over the elements of the list. The first argument is a function that addresses the seed value, this can be any object of any type which will then become the resulting typed value. The second argument is a function that takes the current state and element in the iteration and returns the new state after transformations have been applied.


import arrow.core.NonEmptyList

//sampleStart
fun sumNel(nel: NonEmptyList<Int>): Int =
 nel.foldLeft(0) { acc, n -> acc + n }
val value = sumNel(NonEmptyList.of(1, 1, 1, 1))
//sampleEnd
fun main() {
 println("value = $value")
}

map

map allows us to transform A into B in NonEmptyList< A >


import arrow.core.NonEmptyList

val value =
//sampleStart
 NonEmptyList.of(1, 1, 1, 1).map { it + 1 }
//sampleEnd
fun main() {
 println(value)
}

flatMap

flatMap allows us to compute over the contents of multiple NonEmptyList< * > values


import arrow.core.NonEmptyList

//sampleStart
val nelOne: NonEmptyList<Int> = NonEmptyList.of(1)
val nelTwo: NonEmptyList<Int> = NonEmptyList.of(2)

val value = nelOne.flatMap { one ->
 nelTwo.map { two ->
   one + two
 }
}
//sampleEnd
fun main() {
 println("value = $value")
}

Monad binding

Λrrow allows imperative style comprehensions to make computing over NonEmptyList values easy.


import arrow.core.NonEmptyList
import arrow.core.extensions.fx

//sampleStart
val nelOne: NonEmptyList<Int> = NonEmptyList.of(1)
val nelTwo: NonEmptyList<Int> = NonEmptyList.of(2)
val nelThree: NonEmptyList<Int> = NonEmptyList.of(3)

val value = NonEmptyList.fx {
 val (one) = nelOne
 val (two) = nelTwo
 val (three) = nelThree
 one + two + three
}
//sampleEnd
fun main() {
 println("value = $value")
}

Monad binding in NonEmptyList and other collection related data type can be used as generators


import arrow.core.NonEmptyList
import arrow.core.extensions.fx

val value =
//sampleStart
 NonEmptyList.fx {
   val (x) = NonEmptyList.of(1, 2, 3)
   val (y) = NonEmptyList.of(1, 2, 3)
  x + y
 }
//sampleEnd
fun main() {
 println(value)
}

Applicative Builder

Λrrow contains methods that allow you to preserve type information when computing over different NonEmptyList typed values.


import arrow.core.NonEmptyList
import java.util.UUID
import arrow.core.extensions.nonemptylist.apply.map

//sampleStart
data class Person(val id: UUID, val name: String, val year: Int)

// Note each NonEmptyList is of a different type
val nelId: NonEmptyList<UUID> = NonEmptyList.of(UUID.randomUUID(), UUID.randomUUID())
val nelName: NonEmptyList<String> = NonEmptyList.of("William Alvin Howard", "Haskell Curry")
val nelYear: NonEmptyList<Int> = NonEmptyList.of(1926, 1900)

val value = map(nelId, nelName, nelYear) { (id, name, year) ->
 Person(id, name, year)
}
//sampleEnd
fun main() {
 println("value = $value")
}

Summary

  • NonEmptyList is used to model lists that guarantee at least one element
  • We can easily construct values of NonEmptyList with NonEmptyList.of
  • foldLeft, map, flatMap and others are used to compute over the internal contents of a NonEmptyList value.
  • fx { ... } comprehensions can be used to imperatively compute over multiple NonEmptyList values in sequence.
  • NonEmptyList.applicative().map { ... } can be used to compute over multiple NonEmptyList values preserving type information and abstracting over arity with map

Supported type classes

Module Type classes
arrow.aql Count, From, GroupBy, Max, Min, OrderBy, Select, Sum, Union
arrow.optics.typeclasses Each, FilterIndex, Index
arrow.recursion.typeclasses Birecursive, Corecursive, Recursive
arrow.typeclasses Applicative, Apply, Bimonad, Comonad, Eq, Foldable, Functor, Hash, Monad, Semigroup, SemigroupK, Show, Traverse

Constructors

<init> NonEmptyList(head: A, tail: List<A>)

Properties

all val all: List<A>
head val head: A
size val size: Int
tail val tail: List<A>

Functions

ap fun <B> ap(ff: <ERROR CLASS><(A) -> B>): NonEmptyList<B>
coflatMap fun <B> coflatMap(f: (<ERROR CLASS><A>) -> B): NonEmptyList<B>
contains fun contains(element: A): Boolean
containsAll fun containsAll(elements: Collection<A>): Boolean
equals fun equals(other: Any?): Boolean
extract fun extract(): A
flatMap fun <B> flatMap(f: (A) -> <ERROR CLASS><B>): NonEmptyList<B>
foldLeft fun <B> foldLeft(b: B, f: (B, A) -> B): B
foldRight fun <B> foldRight(lb: Eval<B>, f: (A, Eval<B>) -> Eval<B>): Eval<B>
hashCode fun hashCode(): Int
isEmpty fun isEmpty(): Boolean
iterator fun iterator(): Iterator<A>
map fun <B> map(f: (A) -> B): NonEmptyList<B>
plus operator fun plus(l: NonEmptyList<A>): NonEmptyList<A>
operator fun plus(l: List<A>): NonEmptyList<A>
operator fun plus(a: A): NonEmptyList<A>
toList fun toList(): List<A>
toString fun toString(): String
traverse fun <G, B> traverse(AG: Applicative<G>, f: (A) -> Kind<G, B>): Kind<G, NonEmptyList<B>>

Companion Object Functions

fromList fun <A> fromList(l: List<A>): Option<NonEmptyList<A>>
fromListUnsafe fun <A> fromListUnsafe(l: List<A>): NonEmptyList<A>
invoke operator fun <A> invoke(head: A, vararg t: A): NonEmptyList<A>
just fun <A> just(a: A): NonEmptyList<A>
of fun <A> of(head: A, vararg t: A): NonEmptyList<A>
tailRecM fun <A, B> tailRecM(a: A, f: (A) -> Kind<<ERROR CLASS>, Either<A, B>>): NonEmptyList<B>

Type Class Hierarchy