Documentation

Batteries.Data.List.Basic

New definitions #

def List.bagInter {α : Type u_1} [BEq α] :
List αList αList α

Computes the "bag intersection" of l₁ and l₂, that is, the collection of elements of l₁ which are also in l₂. As each element is identified, it is removed from l₂, so elements are counted with multiplicity.

Equations
def List.diff {α : Type u_1} [BEq α] :
List αList αList α

Computes the difference of l₁ and l₂, by removing each element in l₂ from l₁.

Equations
@[inline]
def List.next? {α : Type u_1} :
List αOption (α × List α)

Get the head and tail of a list, if it is nonempty.

Equations
@[specialize #[]]
def List.after {α : Type u_1} (p : αBool) :
List αList α

after p xs is the suffix of xs after the first element that satisfies p, not including that element.

after      (· == 1) [0, 1, 2, 3] = [2, 3]
drop_while (· != 1) [0, 1, 2, 3] = [1, 2, 3]
Equations
def List.replaceF {α : Type u_1} (f : αOption α) :
List αList α

Replaces the first element of the list for which f returns some with the returned value.

Equations
@[inline]
def List.replaceFTR {α : Type u_1} (f : αOption α) (l : List α) :
List α

Tail-recursive version of replaceF.

Equations
@[specialize #[]]
def List.replaceFTR.go {α : Type u_1} (f : αOption α) :
List αArray αList α

Auxiliary for replaceFTR: replaceFTR.go f xs acc = acc.toList ++ replaceF f xs.

Equations
theorem List.replaceF_eq_replaceFTR.go (α : Type u_1) (p : αOption α) (acc : Array α) (xs : List α) :
replaceFTR.go p xs acc = acc.toList ++ replaceF p xs
@[inline]
def List.union {α : Type u_1} [BEq α] (l₁ l₂ : List α) :
List α

Constructs the union of two lists, by inserting the elements of l₁ in reverse order to l₂. As a result, l₂ will always be a suffix, but only the last occurrence of each element in l₁ will be retained (but order will otherwise be preserved).

Equations
@[inline]
def List.inter {α : Type u_1} [BEq α] (l₁ l₂ : List α) :
List α

Constructs the intersection of two lists, by filtering the elements of l₁ that are in l₂. Unlike bagInter this does not preserve multiplicity: [1, 1].inter [1] is [1, 1].

Equations
def List.splitAtD {α : Type u_1} (n : Nat) (l : List α) (dflt : α) :
List α × List α

Split a list at an index. Ensures the left list always has the specified length by right padding with the provided default element.

splitAtD 2 [a, b, c] x = ([a, b], [c])
splitAtD 4 [a, b, c] x = ([a, b, c, x], [])
Equations
def List.splitAtD.go {α : Type u_1} (dflt : α) :
NatList αList αList α × List α

Auxiliary for splitAtD: splitAtD.go dflt n l acc = (acc.reverse ++ left, right) if splitAtD n l dflt = (left, right).

Equations
def List.splitOnP {α : Type u_1} (P : αBool) (l : List α) :
List (List α)

Split a list at every element satisfying a predicate. The separators are not in the result.

[1, 1, 2, 3, 2, 4, 4].splitOnP (· == 2) = [[1, 1], [3], [4, 4]]
Equations
def List.splitOnP.go {α : Type u_1} (P : αBool) :
List αList αList (List α)

Auxiliary for splitOnP: splitOnP.go xs acc = res' where res' is obtained from splitOnP P xs by prepending acc.reverse to the first element.

Equations
@[inline]
def List.splitOnPTR {α : Type u_1} (P : αBool) (l : List α) :
List (List α)

Tail recursive version of splitOnP.

Equations
@[specialize #[]]
def List.splitOnPTR.go {α : Type u_1} (P : αBool) :
List αArray αArray (List α)List (List α)

Auxiliary for splitOnP: splitOnP.go xs acc r = r.toList ++ res' where res' is obtained from splitOnP P xs by prepending acc.toList to the first element.

Equations
@[inline]
def List.splitOn {α : Type u_1} [BEq α] (a : α) (as : List α) :
List (List α)

Split a list at every occurrence of a separator element. The separators are not in the result.

[1, 1, 2, 3, 2, 4, 4].splitOn 2 = [[1, 1], [3], [4, 4]]
Equations
@[deprecated List.modifyTailIdx (since := "2024-10-21")]
def List.modifyNthTail {α : Type u} (f : List αList α) :
NatList αList α

Alias of List.modifyTailIdx.


Apply a function to the nth tail of l. Returns the input without using f if the index is larger than the length of the List.

modifyTailIdx f 2 [a, b, c] = [a, b] ++ f [c]
Equations
@[deprecated List.modify (since := "2024-10-21")]
def List.modifyNth {α : Type u} (f : αα) :
NatList αList α

Alias of List.modify.


Apply f to the nth element of the list, if it exists, replacing that element with the result.

Equations
@[inline]
def List.modifyLast {α : Type u_1} (f : αα) (l : List α) :
List α

Apply f to the last element of l, if it exists.

Equations
@[specialize #[]]
def List.modifyLast.go {α : Type u_1} (f : αα) :
List αArray αList α

Auxiliary for modifyLast: modifyLast.go f l acc = acc.toList ++ modifyLast f l.

Equations
@[deprecated List.insertIdx (since := "2024-10-21")]
def List.insertNth {α : Type u} (i : Nat) (a : α) :
List αList α

Alias of List.insertIdx.


insertIdx n a l inserts a into the list l after the first n elements of l

insertIdx 2 1 [1, 2, 3, 4] = [1, 2, 1, 3, 4]
Equations
theorem List.headD_eq_head? {α : Type u_1} (l : List α) (a : α) :
l.headD a = l.head?.getD a
def List.takeD {α : Type u_1} :
NatList ααList α

Take n elements from a list l. If l has less than n elements, append n - length l elements x.

Equations
@[simp]
theorem List.takeD_zero {α : Type u_1} (l : List α) (a : α) :
takeD 0 l a = []
@[simp]
theorem List.takeD_succ {α : Type u_1} {n : Nat} (l : List α) (a : α) :
takeD (n + 1) l a = l.head?.getD a :: takeD n l.tail a
@[simp]
theorem List.takeD_nil {α : Type u_1} (n : Nat) (a : α) :
def List.takeDTR {α : Type u_1} (n : Nat) (l : List α) (dflt : α) :
List α

Tail-recursive version of takeD.

Equations
def List.takeDTR.go {α : Type u_1} (dflt : α) :
NatList αArray αList α

Auxiliary for takeDTR: takeDTR.go dflt n l acc = acc.toList ++ takeD n l dflt.

Equations
theorem List.takeDTR_go_eq {α✝ : Type u_1} {dflt : α✝} {acc : Array α✝} (n : Nat) (l : List α✝) :
takeDTR.go dflt n l acc = acc.toList ++ takeD n l dflt
def List.scanl {α : Type u_1} {β : Type u_2} (f : αβα) (a : α) :
List βList α

Fold a function f over the list from the left, returning the list of partial results.

scanl (+) 0 [1, 2, 3] = [0, 1, 3, 6]
Equations
@[inline]
def List.scanlTR {α : Type u_1} {β : Type u_2} (f : αβα) (a : α) (l : List β) :
List α

Tail-recursive version of scanl.

Equations
@[specialize #[]]
def List.scanlTR.go {α : Type u_1} {β : Type u_2} (f : αβα) :
List βαArray αList α

Auxiliary for scanlTR: scanlTR.go f l a acc = acc.toList ++ scanl f a l.

Equations
theorem List.scanlTR_go_eq {α✝ : Type u_1} {α✝¹ : Type u_2} {f : α✝α✝¹α✝} {a : α✝} {acc : Array α✝} (l : List α✝¹) :
scanlTR.go f l a acc = acc.toList ++ scanl f a l
def List.scanr {α : Type u_1} {β : Type u_2} (f : αββ) (b : β) (l : List α) :
List β

Fold a function f over the list from the right, returning the list of partial results.

scanr (+) 0 [1, 2, 3] = [6, 5, 3, 0]
Equations
@[specialize #[]]
def List.foldlIdx {α : Sort u_1} {β : Type u_2} (f : Natαβα) (init : α) :
List β(start : optParam Nat 0) → α

Fold a list from left to right as with foldl, but the combining function also receives each element's index.

Equations
@[specialize #[]]
def List.foldrIdx {α : Type u_1} {β : Sort u_2} (f : Natαββ) (init : β) (l : List α) (start : Nat := 0) :
β

Fold a list from right to left as with foldr, but the combining function also receives each element's index.

Equations
@[inline]
def List.findIdxs {α : Type u_1} (p : αBool) (l : List α) :

findIdxs p l is the list of indexes of elements of l that satisfy p.

Equations
@[inline]
def List.indexesValues {α : Type u_1} (p : αBool) (l : List α) :
List (Nat × α)

Returns the elements of l that satisfy p together with their indexes in l. The returned list is ordered by index.

Equations
@[inline]
def List.indexesOf {α : Type u_1} [BEq α] (a : α) :
List αList Nat

indexesOf a l is the list of all indexes of a in l. For example:

indexesOf a [a, b, a, a] = [0, 2, 3]
Equations
@[inline]
def List.lookmap {α : Type u_1} (f : αOption α) (l : List α) :
List α

lookmap is a combination of lookup and filterMap. lookmap f l will apply f : α → Option α to each element of the list, replacing a → b at the first value a in the list such that f a = some b.

Equations
@[specialize #[]]
def List.lookmap.go {α : Type u_1} (f : αOption α) :
List αArray αList α

Auxiliary for lookmap: lookmap.go f l acc = acc.toList ++ lookmap f l.

Equations
def List.inits {α : Type u_1} :
List αList (List α)

inits l is the list of initial segments of l.

inits [1, 2, 3] = [[], [1], [1, 2], [1, 2, 3]]
Equations
def List.initsTR {α : Type u_1} (l : List α) :
List (List α)

Tail-recursive version of inits.

Equations
def List.tails {α : Type u_1} :
List αList (List α)

tails l is the list of terminal segments of l.

tails [1, 2, 3] = [[1, 2, 3], [2, 3], [3], []]
Equations
def List.tailsTR {α : Type u_1} (l : List α) :
List (List α)

Tail-recursive version of tails.

Equations
def List.tailsTR.go {α : Type u_1} (l : List α) (acc : Array (List α)) :
List (List α)

Auxiliary for tailsTR: tailsTR.go l acc = acc.toList ++ tails l.

Equations
def List.sublists' {α : Type u_1} (l : List α) :
List (List α)

sublists' l is the list of all (non-contiguous) sublists of l. It differs from sublists only in the order of appearance of the sublists; sublists' uses the first element of the list as the MSB, sublists uses the first element of the list as the LSB.

sublists' [1, 2, 3] = [[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
Equations
@[implemented_by List.sublistsFast]
def List.sublists {α : Type u_1} (l : List α) :
List (List α)

sublists l is the list of all (non-contiguous) sublists of l; cf. sublists' for a different ordering.

sublists [1, 2, 3] = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
Equations
def List.sublistsFast {α : Type u_1} (l : List α) :
List (List α)

A version of List.sublists that has faster runtime performance but worse kernel performance

Equations
  • One or more equations did not get rendered due to their size.
inductive List.Forall₂ {α : Type u_1} {β : Type u_2} (R : αβProp) :
List αList βProp

Forall₂ R l₁ l₂ means that l₁ and l₂ have the same length, and whenever a is the nth element of l₁, and b is the nth element of l₂, then R a b is satisfied.

@[simp]
theorem List.forall₂_cons {α : Type u_1} {β : Type u_2} {R : αβProp} {a : α} {b : β} {l₁ : List α} {l₂ : List β} :
Forall₂ R (a :: l₁) (b :: l₂) R a b Forall₂ R l₁ l₂
def List.all₂ {α : Type u_1} {β : Type u_2} (r : αβBool) :
List αList βBool

Check for all elements a, b, where a and b are the nth element of the first and second List respectively, that r a b = true.

Equations
@[simp]
theorem List.all₂_eq_true {α : Type u_1} {β : Type u_2} {r : αβBool} (l₁ : List α) (l₂ : List β) :
all₂ r l₁ l₂ = true Forall₂ (fun (x1 : α) (x2 : β) => r x1 x2 = true) l₁ l₂
instance List.instDecidableForall₂ {α : Type u_1} {β : Type u_2} {R : αβProp} [(a : α) → (b : β) → Decidable (R a b)] (l₁ : List α) (l₂ : List β) :
Decidable (Forall₂ R l₁ l₂)
Equations
def List.transpose {α : Type u_1} (l : List (List α)) :
List (List α)

Transpose of a list of lists, treated as a matrix.

transpose [[1, 2], [3, 4], [5, 6]] = [[1, 3, 5], [2, 4, 6]]
Equations
def List.transpose.pop {α : Type u_1} (old : List α) :
List αId (List α × List α)

pop : List α → StateM (List α) (List α) transforms the input list old by taking the head of the current state and pushing it on the head of old. If the state list is empty, then old is left unchanged.

Equations
def List.transpose.go {α : Type u_1} (l : List α) (acc : Array (List α)) :
Array (List α)

go : List α → Array (List α) → Array (List α) handles the insertion of a new list into all the lists in the array: go [a, b, c] #[l₁, l₂, l₃] = #[a::l₁, b::l₂, c::l₃]. If the new list is too short, the later lists are unchanged, and if it is too long the array is extended:

go [a] #[l₁, l₂, l₃] = #[a::l₁, l₂, l₃]
go [a, b, c, d] #[l₁, l₂, l₃] = #[a::l₁, b::l₂, c::l₃, [d]]
Equations
def List.sections {α : Type u_1} :
List (List α)List (List α)

List of all sections through a list of lists. A section of [L₁, L₂, ..., Lₙ] is a list whose first element comes from L₁, whose second element comes from L₂, and so on.

Equations
def List.sectionsTR {α : Type u_1} (L : List (List α)) :
List (List α)

Optimized version of sections.

Equations
def List.sectionsTR.go {α : Type u_1} (l : List α) (acc : Array (List α)) :
Array (List α)

go : List α → Array (List α) → Array (List α) inserts one list into the accumulated list of sections acc: go [a, b] #[l₁, l₂] = [a::l₁, b::l₁, a::l₂, b::l₂].

Equations
def List.extractP {α : Type u_1} (p : αBool) (l : List α) :
Option α × List α

extractP p l returns a pair of an element a of l satisfying the predicate p, and l, with a removed. If there is no such element a it returns (none, l).

Equations
def List.extractP.go {α : Type u_1} (p : αBool) (l : List α) :
List αArray αOption α × List α

Auxiliary for extractP: extractP.go p l xs acc = (some a, acc.toList ++ out) if extractP p xs = (some a, out), and extractP.go p l xs acc = (none, l) if extractP p xs = (none, _).

Equations
def List.revzip {α : Type u_1} (l : List α) :
List (α × α)

revzip l returns a list of pairs of the elements of l paired with the elements of l in reverse order.

revzip [1, 2, 3, 4, 5] = [(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)]
Equations
def List.product {α : Type u_1} {β : Type u_2} (l₁ : List α) (l₂ : List β) :
List (α × β)

product l₁ l₂ is the list of pairs (a, b) where a ∈ l₁ and b ∈ l₂.

product [1, 2] [5, 6] = [(1, 5), (1, 6), (2, 5), (2, 6)]
Equations
def List.productTR {α : Type u_1} {β : Type u_2} (l₁ : List α) (l₂ : List β) :
List (α × β)

Optimized version of product.

Equations
def List.sigma {α : Type u_1} {σ : αType u_2} (l₁ : List α) (l₂ : (a : α) → List (σ a)) :
List ((a : α) × σ a)

sigma l₁ l₂ is the list of dependent pairs (a, b) where a ∈ l₁ and b ∈ l₂ a.

sigma [1, 2] (λ_, [(5 : Nat), 6]) = [(1, 5), (1, 6), (2, 5), (2, 6)]
Equations
def List.sigmaTR {α : Type u_1} {σ : αType u_2} (l₁ : List α) (l₂ : (a : α) → List (σ a)) :
List ((a : α) × σ a)

Optimized version of sigma.

Equations
def List.ofFnNthVal {α : Type u_1} {n : Nat} (f : Fin nα) (i : Nat) :

ofFnNthVal f i returns some (f i) if i < n and none otherwise.

Equations
def List.Disjoint {α : Type u_1} (l₁ l₂ : List α) :

Disjoint l₁ l₂ means that l₁ and l₂ have no elements in common.

Equations
def List.takeWhile₂ {α : Type u_1} {β : Type u_2} (R : αβBool) :
List αList βList α × List β

Returns the longest initial prefix of two lists such that they are pairwise related by R.

takeWhile₂ (· < ·) [1, 2, 4, 5] [5, 4, 3, 6] = ([1, 2], [5, 4])
Equations
@[inline]
def List.takeWhile₂TR {α : Type u_1} {β : Type u_2} (R : αβBool) (as : List α) (bs : List β) :
List α × List β

Tail-recursive version of takeWhile₂.

Equations
@[specialize #[]]
def List.takeWhile₂TR.go {α : Type u_1} {β : Type u_2} (R : αβBool) :
List αList βList αList βList α × List β

Auxiliary for takeWhile₂TR: takeWhile₂TR.go R as bs acca accb = (acca.reverse ++ as', acca.reverse ++ bs') if takeWhile₂ R as bs = (as', bs').

Equations
@[irreducible]
theorem List.takeWhile₂_eq_takeWhile₂TR.go (α : Type u_2) (β : Type u_1) (R : αβBool) (as : List α) (bs : List β) (acca : List α) (accb : List β) :
takeWhile₂TR.go R as bs acca accb = (acca.reverse ++ (takeWhile₂ R as bs).fst, accb.reverse ++ (takeWhile₂ R as bs).snd)
def List.pwFilter {α : Type u_1} (R : ααProp) [DecidableRel R] (l : List α) :
List α

pwFilter R l is a maximal sublist of l which is Pairwise R. pwFilter (·≠·) is the erase duplicates function (cf. eraseDup), and pwFilter (·<·) finds a maximal increasing subsequence in l. For example,

pwFilter (·<·) [0, 1, 5, 2, 6, 3, 4] = [0, 1, 2, 3, 4]
Equations
inductive List.Chain {α : Type u_1} (R : ααProp) :
αList αProp

Chain R a l means that R holds between adjacent elements of a::l.

Chain R a [b, c, d] ↔ R a b ∧ R b c ∧ R c d
  • nil {α : Type u_1} {R : ααProp} {a : α} : Chain R a []

    A chain of length 1 is trivially a chain.

  • cons {α : Type u_1} {R : ααProp} {a b : α} {l : List α} : R a bChain R b lChain R a (b :: l)

    If a relates to b and b::l is a chain, then a :: b :: l is also a chain.

Instances For
def List.Chain' {α : Type u_1} (R : ααProp) :
List αProp

Chain' R l means that R holds between adjacent elements of l.

Chain' R [a, b, c, d] ↔ R a b ∧ R b c ∧ R c d
Equations
Instances For
@[inline]
def List.eraseDup {α : Type u_1} [BEq α] :
List αList α

eraseDup l removes duplicates from l (taking only the first occurrence). Defined as pwFilter (≠).

eraseDup [1, 0, 2, 2, 1] = [0, 2, 1] 
Equations
@[inline]
def List.rotate {α : Type u_1} (l : List α) (n : Nat) :
List α

rotate l n rotates the elements of l to the left by n

rotate [0, 1, 2, 3, 4, 5] 2 = [2, 3, 4, 5, 0, 1]
Equations
def List.rotate' {α : Type u_1} :
List αNatList α

rotate' is the same as rotate, but slower. Used for proofs about rotate

Equations
def List.mapDiagM {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] (f : ααm β) (l : List α) :
m (List β)

mapDiagM f l calls f on all elements in the upper triangular part of l × l. That is, for each e ∈ l, it will run f e e and then f e e' for each e' that appears after e in l.

mapDiagM f [1, 2, 3] =
  return [← f 1 1, ← f 1 2, ← f 1 3, ← f 2 2, ← f 2 3, ← f 3 3]
Equations
def List.mapDiagM.go {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] (f : ααm β) :
List αArray βm (List β)

Auxiliary for mapDiagM: mapDiagM.go as f acc = (acc.toList ++ ·) <$> mapDiagM f as

Equations
def List.forDiagM {m : Type u_1 → Type u_2} {α : Type u_3} [Monad m] (f : ααm PUnit) :
List αm PUnit

forDiagM f l calls f on all elements in the upper triangular part of l × l. That is, for each e ∈ l, it will run f e e and then f e e' for each e' that appears after e in l.

forDiagM f [1, 2, 3] = do f 1 1; f 1 2; f 1 3; f 2 2; f 2 3; f 3 3
Equations
def List.getRest {α : Type u_1} [DecidableEq α] :
List αList αOption (List α)

getRest l l₁ returns some l₂ if l = l₁ ++ l₂. If l₁ is not a prefix of l, returns none

Equations
def List.dropSlice {α : Type u_1} :
NatNatList αList α

List.dropSlice n m xs removes a slice of length m at index n in list xs.

Equations
@[inline]
def List.dropSliceTR {α : Type u_1} (n m : Nat) (l : List α) :
List α

Optimized version of dropSlice.

Equations
def List.dropSliceTR.go {α : Type u_1} (l : List α) (m : Nat) :
List αNatArray αList α

Auxiliary for dropSliceTR: dropSliceTR.go l m xs n acc = acc.toList ++ dropSlice n m xs unless n ≥ length xs, in which case it is l.

Equations
theorem List.dropSlice_zero₂ {α : Type u_1} (n : Nat) (l : List α) :
dropSlice n 0 l = l
theorem List.dropSlice_eq_dropSliceTR.go (α : Type u_1) (l : List α) (m : Nat) (acc : Array α) (xs : List α) (n : Nat) :
l = acc.toList ++ xsdropSliceTR.go l m xs n acc = acc.toList ++ dropSlice n (m + 1) xs
def List.zipWithLeft' {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : αOption βγ) :
List αList βList γ × List β

Left-biased version of List.zipWith. zipWithLeft' f as bs applies f to each pair of elements aᵢ ∈ as and bᵢ ∈ bs. If bs is shorter than as, f is applied to none for the remaining aᵢ. Returns the results of the f applications and the remaining bs.

zipWithLeft' prod.mk [1, 2] ['a'] = ([(1, some 'a'), (2, none)], [])
zipWithLeft' prod.mk [1] ['a', 'b'] = ([(1, some 'a')], ['b'])
Equations
@[inline]
def List.zipWithLeft'TR {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : αOption βγ) (as : List α) (bs : List β) :
List γ × List β

Tail-recursive version of zipWithLeft'.

Equations
def List.zipWithLeft'TR.go {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : αOption βγ) :
List αList βArray γList γ × List β

Auxiliary for zipWithLeft'TR: zipWithLeft'TR.go l acc = acc.toList ++ zipWithLeft' l.

Equations
theorem List.zipWithLeft'_eq_zipWithLeft'TR.go (α : Type u_3) (β : Type u_2) (γ : Type u_1) (f : αOption βγ) (acc : Array γ) (as : List α) (bs : List β) :
zipWithLeft'TR.go f as bs acc = match zipWithLeft' f as bs with | (l, r) => (acc.toList ++ l, r)
@[inline]
def List.zipWithRight' {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : Option αβγ) (as : List α) (bs : List β) :
List γ × List α

Right-biased version of List.zipWith. zipWithRight' f as bs applies f to each pair of elements aᵢ ∈ as and bᵢ ∈ bs. If as is shorter than bs, f is applied to none for the remaining bᵢ. Returns the results of the f applications and the remaining as.

zipWithRight' prod.mk [1] ['a', 'b'] = ([(some 1, 'a'), (none, 'b')], [])
zipWithRight' prod.mk [1, 2] ['a'] = ([(some 1, 'a')], [2])
Equations
@[inline]
def List.zipLeft' {α : Type u_1} {β : Type u_2} :
List αList βList (α × Option β) × List β

Left-biased version of List.zip. zipLeft' as bs returns the list of pairs (aᵢ, bᵢ) for aᵢ ∈ as and bᵢ ∈ bs. If bs is shorter than as, the remaining aᵢ are paired with none. Also returns the remaining bs.

zipLeft' [1, 2] ['a'] = ([(1, some 'a'), (2, none)], [])
zipLeft' [1] ['a', 'b'] = ([(1, some 'a')], ['b'])
zipLeft' = zipWithLeft' prod.mk
Equations
@[inline]
def List.zipRight' {α : Type u_1} {β : Type u_2} :
List αList βList (Option α × β) × List α

Right-biased version of List.zip. zipRight' as bs returns the list of pairs (aᵢ, bᵢ) for aᵢ ∈ as and bᵢ ∈ bs. If as is shorter than bs, the remaining bᵢ are paired with none. Also returns the remaining as.

zipRight' [1] ['a', 'b'] = ([(some 1, 'a'), (none, 'b')], [])
zipRight' [1, 2] ['a'] = ([(some 1, 'a')], [2])
zipRight' = zipWithRight' prod.mk
Equations
def List.zipWithLeft {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : αOption βγ) :
List αList βList γ

Left-biased version of List.zipWith. zipWithLeft f as bs applies f to each pair aᵢ ∈ as and bᵢ ‌∈ bs‌∈ bs. If bs is shorter than as, f is applied to none for the remaining aᵢ.

zipWithLeft prod.mk [1, 2] ['a'] = [(1, some 'a'), (2, none)]
zipWithLeft prod.mk [1] ['a', 'b'] = [(1, some 'a')]
zipWithLeft f as bs = (zipWithLeft' f as bs).fst
Equations
@[inline]
def List.zipWithLeftTR {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : αOption βγ) (as : List α) (bs : List β) :
List γ

Tail-recursive version of zipWithLeft.

Equations
def List.zipWithLeftTR.go {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : αOption βγ) :
List αList βArray γList γ

Auxiliary for zipWithLeftTR: zipWithLeftTR.go l acc = acc.toList ++ zipWithLeft l.

Equations
theorem List.zipWithLeft_eq_zipWithLeftTR.go (α : Type u_3) (β : Type u_2) (γ : Type u_1) (f : αOption βγ) (acc : Array γ) (as : List α) (bs : List β) :
zipWithLeftTR.go f as bs acc = acc.toList ++ zipWithLeft f as bs
@[inline]
def List.zipWithRight {α : Type u_1} {β : Type u_2} {γ : Type u_3} (f : Option αβγ) (as : List α) (bs : List β) :
List γ

Right-biased version of List.zipWith. zipWithRight f as bs applies f to each pair aᵢ ∈ as and bᵢ ‌∈ bs‌∈ bs. If as is shorter than bs, f is applied to none for the remaining bᵢ.

zipWithRight prod.mk [1, 2] ['a'] = [(some 1, 'a')]
zipWithRight prod.mk [1] ['a', 'b'] = [(some 1, 'a'), (none, 'b')]
zipWithRight f as bs = (zipWithRight' f as bs).fst
Equations
@[inline]
def List.zipLeft {α : Type u_1} {β : Type u_2} :
List αList βList (α × Option β)

Left-biased version of List.zip. zipLeft as bs returns the list of pairs (aᵢ, bᵢ) for aᵢ ∈ as and bᵢ ∈ bs. If bs is shorter than as, the remaining aᵢ are paired with none.

zipLeft [1, 2] ['a'] = [(1, some 'a'), (2, none)]
zipLeft [1] ['a', 'b'] = [(1, some 'a')]
zipLeft = zipWithLeft prod.mk
Equations
@[inline]
def List.zipRight {α : Type u_1} {β : Type u_2} :
List αList βList (Option α × β)

Right-biased version of List.zip. zipRight as bs returns the list of pairs (aᵢ, bᵢ) for aᵢ ∈ as and bᵢ ∈ bs. If as is shorter than bs, the remaining bᵢ are paired with none.

zipRight [1, 2] ['a'] = [(some 1, 'a')]
zipRight [1] ['a', 'b'] = [(some 1, 'a'), (none, 'b')]
zipRight = zipWithRight prod.mk
Equations
@[inline]
def List.allSome {α : Type u_1} (l : List (Option α)) :

If all elements of xs are some xᵢ, allSome xs returns the xᵢ. Otherwise it returns none.

allSome [some 1, some 2] = some [1, 2]
allSome [some 1, none  ] = none
Equations
def List.fillNones {α : Type u_1} :
List (Option α)List αList α

fillNones xs ys replaces the nones in xs with elements of ys. If there are not enough ys to replace all the nones, the remaining nones are dropped from xs.

fillNones [none, some 1, none, none] [2, 3] = [2, 1, 3]
Equations
@[inline]
def List.fillNonesTR {α : Type u_1} (as : List (Option α)) (as' : List α) :
List α

Tail-recursive version of fillNones.

Equations
def List.fillNonesTR.go {α : Type u_1} :
List (Option α)List αArray αList α

Auxiliary for fillNonesTR: fillNonesTR.go as as' acc = acc.toList ++ fillNones as as'.

Equations
theorem List.fillNones_eq_fillNonesTR.go (α : Type u_1) (acc : Array α) (as : List (Option α)) (as' : List α) :
fillNonesTR.go as as' acc = acc.toList ++ as.fillNones as'
def List.takeList {α : Type u_1} :
List αList NatList (List α) × List α

takeList as ns extracts successive sublists from as. For ns = n₁ ... nₘ, it first takes the n₁ initial elements from as, then the next n₂ ones, etc. It returns the sublists of as -- one for each nᵢ -- and the remaining elements of as. If as does not have at least as many elements as the sum of the nᵢ, the corresponding sublists will have less than nᵢ elements.

takeList ['a', 'b', 'c', 'd', 'e'] [2, 1, 1] = ([['a', 'b'], ['c'], ['d']], ['e'])
takeList ['a', 'b'] [3, 1] = ([['a', 'b'], []], [])
Equations
@[inline]
def List.takeListTR {α : Type u_1} (xs : List α) (ns : List Nat) :
List (List α) × List α

Tail-recursive version of takeList.

Equations
def List.takeListTR.go {α : Type u_1} :
List NatList αArray (List α)List (List α) × List α

Auxiliary for takeListTR: takeListTR.go as as' acc = acc.toList ++ takeList as as'.

Equations
theorem List.takeList_eq_takeListTR.go (α : Type u_1) (acc : Array (List α)) (ns : List Nat) (xs : List α) :
takeListTR.go ns xs acc = match xs.takeList ns with | (l, r) => (acc.toList ++ l, r)
def List.toChunksAux {α : Type u_1} (n : Nat) :
List αNatList α × List (List α)

Auxliary definition used to define toChunks. toChunksAux n xs i returns (xs.take i, (xs.drop i).toChunks (n+1)), that is, the first i elements of xs, and the remaining elements chunked into sublists of length n+1.

Equations
def List.toChunks {α : Type u_1} :
NatList αList (List α)

xs.toChunks n splits the list into sublists of size at most n, such that (xs.toChunks n).join = xs.

[1, 2, 3, 4, 5, 6, 7, 8].toChunks 10 = [[1, 2, 3, 4, 5, 6, 7, 8]]
[1, 2, 3, 4, 5, 6, 7, 8].toChunks 3 = [[1, 2, 3], [4, 5, 6], [7, 8]]
[1, 2, 3, 4, 5, 6, 7, 8].toChunks 2 = [[1, 2], [3, 4], [5, 6], [7, 8]]
[1, 2, 3, 4, 5, 6, 7, 8].toChunks 0 = [[1, 2, 3, 4, 5, 6, 7, 8]]
Equations
def List.toChunks.go {α : Type u_1} (n : Nat) :
List αArray αArray (List α)List (List α)

Auxliary definition used to define toChunks. toChunks.go xs acc₁ acc₂ pushes elements into acc₁ until it reaches size n, then it pushes the resulting list to acc₂ and continues until xs is exhausted.

Equations

We add some n-ary versions of List.zipWith for functions with more than two arguments. These can also be written in terms of List.zip or List.zipWith. For example, zipWith₃ f xs ys zs could also be written as zipWith id (zipWith f xs ys) zs or as (zip xs <| zip ys zs).map fun ⟨x, y, z⟩ => f x y z.

def List.zipWith₃ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} (f : αβγδ) :
List αList βList γList δ

Ternary version of List.zipWith.

Equations
def List.zipWith₄ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {ε : Type u_5} (f : αβγδε) :
List αList βList γList δList ε

Quaternary version of List.zipWith.

Equations
def List.zipWith₅ {α : Type u_1} {β : Type u_2} {γ : Type u_3} {δ : Type u_4} {ε : Type u_5} {ζ : Type u_6} (f : αβγδεζ) :
List αList βList γList δList εList ζ

Quinary version of List.zipWith.

Equations
def List.mapWithPrefixSuffixAux {α : Type u_1} {β : Type u_2} (f : List ααList αβ) :
List αList αList β

An auxiliary function for List.mapWithPrefixSuffix.

Equations
def List.mapWithPrefixSuffix {α : Type u_1} {β : Type u_2} (f : List ααList αβ) (l : List α) :
List β

List.mapWithPrefixSuffix f l maps f across a list l. For each a ∈ l with l = pref ++ [a] ++ suff, a is mapped to f pref a suff. Example: if f : list NatNat → list Nat → β, List.mapWithPrefixSuffix f [1, 2, 3] will produce the list [f [] 1 [2, 3], f [1] 2 [3], f [1, 2] 3 []].

Equations
def List.mapWithComplement {α : Type u_1} {β : Type u_2} (f : αList αβ) :
List αList β

List.mapWithComplement f l is a variant of List.mapWithPrefixSuffix that maps f across a list l. For each a ∈ l with l = pref ++ [a] ++ suff, a is mapped to f a (pref ++ suff), i.e., the list input to f is l with a removed. Example: if f : Nat → list Nat → β, List.mapWithComplement f [1, 2, 3] will produce the list [f 1 [2, 3], f 2 [1, 3], f 3 [1, 2]].

Equations
def List.traverse {F : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Applicative F] (f : αF β) :
List αF (List β)

Map each element of a List to an action, evaluate these actions in order, and collect the results.

Equations
def List.Subperm {α : Type u_1} (l₁ l₂ : List α) :

Subperm l₁ l₂, denoted l₁ <+~ l₂, means that l₁ is a sublist of a permutation of l₂. This is an analogue of l₁ ⊆ l₂ which respects multiplicities of elements, and is used for the relation on multisets.

Equations

Subperm l₁ l₂, denoted l₁ <+~ l₂, means that l₁ is a sublist of a permutation of l₂. This is an analogue of l₁ ⊆ l₂ which respects multiplicities of elements, and is used for the relation on multisets.

Equations
def List.isSubperm {α : Type u_1} [BEq α] (l₁ l₂ : List α) :

O(|l₁| * (|l₁| + |l₂|)). Computes whether l₁ is a sublist of a permutation of l₂. See isSubperm_iff for a characterization in terms of List.Subperm.

Equations
def List.insertP {α : Type u_1} (p : αBool) (a : α) (l : List α) :
List α

O(|l|). Inserts a in l right before the first element such that p is true, or at the end of the list if p always false on l.

Equations
def List.insertP.loop {α : Type u_1} (p : αBool) (a : α) :
List αList αList α

Inner loop for insertP. Tail recursive.

Equations
def List.dropPrefix? {α : Type u_1} [BEq α] :
List αList αOption (List α)

dropPrefix? l p returns some r if l = p' ++ r for some p' which is paiwise == to p, and none otherwise.

Equations
def List.dropSuffix? {α : Type u_1} [BEq α] (l s : List α) :

dropSuffix? l s returns some r if l = r ++ s' for some s' which is paiwise == to s, and none otherwise.

Equations
def List.dropInfix? {α : Type u_1} [BEq α] (l i : List α) :
Option (List α × List α)

dropInfix? l i returns some (p, s) if l = p ++ i' ++ s for some i' which is paiwise == to i, and none otherwise.

Note that this is an inefficient implementation, and if computation time is a concern you should be using the Knuth-Morris-Pratt algorithm as implemented in Batteries.Data.List.Matcher.

Equations
def List.dropInfix?.go {α : Type u_1} [BEq α] (i : List α) :
List αList αOption (List α × List α)

Inner loop for dropInfix?.

Equations