aivi.nonEmpty
Types and utilities for non-empty lists — collections that are guaranteed to have at least one element. This guarantee is enforced at the type level, making head and last always safe without returning Option.
use aivi.nonEmpty (
NonEmptyList
singleton
cons
head
last
length
toList
mapNel
fromList
appendNel
fromHeadTail
init
)Type class operations
NonEmptyList implements Functor, Apply, Applicative, Chain, Monad, Foldable, Traversable, Extend, and Comonad. Use ambient map and reduce for generic code; mapNel remains the explicitly named mapping helper. pure creates a singleton. apply applies each function to every input, in function-major order. chain concatenates non-empty results in input order, and join flattens one layer. Semigroup (NonEmptyList A) supplies append, equivalent to appendNel.
traverse transform items sequences effects from head to tail through any Applicative G, producing G (NonEmptyList B). Each successful result keeps the input length and its non-empty guarantee. Traversing into Task builds a deferred plan whose effects run in that order.
extend observe items observes every non-empty suffix, in input order, and preserves length. For [1, 2, 3], those contexts are [1, 2, 3], [2, 3], and [3]. extract items reads the first item, equivalent to head. These operations satisfy the Comonad identities: extend extract items preserves the input, and extract (extend observe items) agrees with observe items.
use aivi.nonEmpty (NonEmptyList, fromHeadTail, toList, length)
value items : NonEmptyList Int = fromHeadTail 1 [2, 3]
value suffixLengths : List Int = toList (extend length items)
value firstItem : Int = extract items
type Comonad W => W A -> W A
func preserve = values => extend extract valuessuffixLengths is [3, 2, 1], and firstItem is 1. The implementation uses list folds, so it does not recurse once per item. Constructing suffix contexts copies a quadratic number of list elements in the current list representation; add the cost of each observer call. Use map when the callback needs only the current item.
There is no Monoid, Default, or Filterable instance: none can promise to retain at least one item for every input allowed by its class signature.
At a glance
| Export | Type | Use it for |
|---|---|---|
NonEmptyList A | Domain over List A | The non-empty list type itself |
singleton | A -> NonEmptyList A | Create a one-item non-empty list |
cons | A -> NonEmptyList A -> NonEmptyList A | Add an item at the front |
head | NonEmptyList A -> A | Read the first item safely |
last | NonEmptyList A -> A | Read the final item safely |
length | NonEmptyList A -> Int | Count items |
toList | NonEmptyList A -> List A | Drop the non-empty guarantee and get a regular list |
mapNel | (A -> B) -> NonEmptyList A -> NonEmptyList B | Transform every item while preserving non-emptiness |
fromList | List A -> Option (NonEmptyList A) | Upgrade a regular list when it is not empty |
fromHeadTail | A -> List A -> NonEmptyList A | Build a non-empty list from a required head and a list tail |
init | NonEmptyList A -> List A | Return every item except the last |
appendNel | NonEmptyList A -> NonEmptyList A -> NonEmptyList A | Concatenate two non-empty lists |
The detailed sections below focus on the most commonly reached-for constructors and transforms; the table above also lists the extra public helpers that are useful in real code, such as fromHeadTail and init.
NonEmptyList
The primary non-empty list type used throughout the standard library, including as the error carrier in aivi.validation.
NonEmptyList A is a domain over List A; its representation is not a public MkNEL constructor. Construct values using singleton, cons, fromHeadTail, or fromList, and read them through the exported accessors.
singleton
Creates a NonEmptyList with exactly one element.
Type: item:A -> NonEmptyList A
use aivi.nonEmpty (
NonEmptyList
singleton
)
type Text -> (NonEmptyList Text)
func wrapOne =
|> singletoncons
Prepends an element to a NonEmptyList.
Type: item:A -> nel:(NonEmptyList A) -> NonEmptyList A
use aivi.nonEmpty (
NonEmptyList
singleton
cons
)
type Int -> Int -> (NonEmptyList Int)
func buildList = first second =>
cons first (singleton second)head
Returns the first element of a NonEmptyList. Always safe — no Option required.
Type: nel:(NonEmptyList A) -> A
use aivi.nonEmpty (
NonEmptyList
head
singleton
)
type NonEmptyList Int -> Int
func firstOf =
|> headlast
Returns the last element of a NonEmptyList. Always safe — no Option required.
Type: nel:(NonEmptyList A) -> A
use aivi.nonEmpty (
NonEmptyList
last
singleton
)
type NonEmptyList Int -> Int
func finalItem =
|> lastlength
Returns the number of elements in the list.
Type: nel:(NonEmptyList A) -> Int
use aivi.nonEmpty (
NonEmptyList
length
singleton
cons
)
type NonEmptyList Int -> Int
func countItems =
|> lengthtoList
Converts a NonEmptyList to a regular List.
Type: nel:(NonEmptyList A) -> List A
use aivi.nonEmpty (
NonEmptyList
toList
singleton
)
type NonEmptyList Int -> (List Int)
func asRegularList =
|> toListmapNel
Applies a function to every element, producing a new NonEmptyList. The non-empty guarantee is preserved.
Type: transform:(A -> B) -> nel:(NonEmptyList A) -> NonEmptyList B
use aivi.nonEmpty (
NonEmptyList
mapNel
)
type Int -> Int
func double = . * 2
type NonEmptyList Int -> (NonEmptyList Int)
func doubleAll =
|> mapNel doublefromList
Attempts to convert a regular List to a NonEmptyList. Returns None if the list is empty.
Type: items:(List A) -> Option (NonEmptyList A)
use aivi.nonEmpty (
NonEmptyList
fromList
)
type List Int -> (Option (NonEmptyList Int))
func safeFromList =
|> fromListUse this when constructing a NonEmptyList from data whose size is not statically known, then handle the None case for empty input.
appendNel
Concatenates two NonEmptyLists into one. The result is always non-empty.
Type: left:(NonEmptyList A) -> right:(NonEmptyList A) -> NonEmptyList A
use aivi.nonEmpty (
NonEmptyList
appendNel
singleton
)
type NonEmptyList Text -> (NonEmptyList Text) -> (NonEmptyList Text)
func combineErrors = a b =>
appendNel a bNonEmptyList is the standard error carrier for applicative validation accumulation.