Non Empty List
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 module under the import arrow.core.NonEmptyList
nonEmptyListOf
A NonEmptyList guarantees the list always has at least 1 element.
import arrow.core.nonEmptyListOf
val value =
//sampleStart
// nonEmptyListOf() // does not compile
nonEmptyListOf(1, 2, 3, 4, 5) // NonEmptyList<Int>
//sampleEnd
fun main() {
println(value)
}head
Unlike List[0], NonEmptyList.head it's a safe operation that guarantees no exception throwing.
import arrow.core.nonEmptyListOf
val value =
//sampleStart
nonEmptyListOf(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
import arrow.core.nonEmptyListOf
//sampleStart
fun sumNel(nel: NonEmptyList<Int>): Int =
nel.foldLeft(0) { acc, n -> acc + n }
val value = sumNel(nonEmptyListOf(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.nonEmptyListOf
val value =
//sampleStart
nonEmptyListOf(1, 1, 1, 1).map { it + 1 }
//sampleEnd
fun main() {
println(value)
}Combining NonEmptyLists
flatMap
flatMap allows us to compute over the contents of multiple NonEmptyList< * > values
import arrow.core.NonEmptyList
import arrow.core.nonEmptyListOf
//sampleStart
val nelOne: NonEmptyList<Int> = nonEmptyListOf(1, 2, 3)
val nelTwo: NonEmptyList<Int> = nonEmptyListOf(4, 5)
val value = nelOne.flatMap { one ->
nelTwo.map { two ->
one + two
}
}
//sampleEnd
fun main() {
println("value = $value")
}zip
Λrrow contains methods that allow you to preserve type information when computing over different NonEmptyList typed values.
import arrow.core.NonEmptyList
import arrow.core.nonEmptyListOf
import arrow.core.zip
import java.util.UUID
//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> = nonEmptyListOf(UUID.randomUUID(), UUID.randomUUID())
val nelName: NonEmptyList<String> = nonEmptyListOf("William Alvin Howard", "Haskell Curry")
val nelYear: NonEmptyList<Int> = nonEmptyListOf(1926, 1900)
val value = nelId.zip(nelName, nelYear) { id, name, year ->
Person(id, name, year)
}
//sampleEnd
fun main() {
println("value = $value")
}Summary
NonEmptyListis used to model lists that guarantee at least one elementWe can easily construct values of
NonEmptyListwithnonEmptyListOffoldLeft,map,flatMapand others are used to compute over the internal contents of aNonEmptyListvalue.a.zip(b, c) { ... }can be used to compute over multipleNonEmptyListvalues preserving type information and abstracting over arity withzip
Constructors
Types
Functions
Properties
Extensions
Combine two A values.