File: .lake/packages/batteries/Batteries/Data/List/Basic.lean

full_name: List.Subset
code: /--
`l₁ ⊆ l₂` means that every element of `l₁` is also an element of `l₂`, ignoring multiplicity.
-/
protected def Subset (l₁ l₂ : List α) 
goal: Prop

full_name: List.«instHasSubset_.lake»
code: instance : HasSubset (List α) 
goal: HasSubset (List α)

full_name: List.«instDecidableRelSubsetOfDecidableEq_.lake»
code: instance [DecidableEq α] : DecidableRel (Subset : List α → List α → Prop) 
goal: DecidableRel Subset

full_name: List.bagInter
code: /--
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.
-/
protected def bagInter {α} [BEq α] : List α → List α → List α
  
goal: List α → List α → List α

full_name: List.diff
code: /-- Computes the difference of `l₁` and `l₂`, by removing each element in `l₂` from `l₁`. -/
protected def diff {α} [BEq α] : List α → List α → List α
  
goal: List α → List α → List α

full_name: List.tail
code: /-- Get the tail of a nonempty list, or return `[]` for `[]`. -/
def tail : List α → List α
  
goal: List α → List α

full_name: List.tail_nil
code: @[simp] theorem tail_nil : @tail α [] = [] 
goal: [].tail = []

full_name: List.tail_cons
code: @[simp] theorem tail_cons : @tail α (a::as) = as 
goal: (a :: as).tail = as

full_name: List.next?
code: /-- Get the head and tail of a list, if it is nonempty. -/
@[inline] def next? : List α → Option (α × List α)
  
goal: List α → Option (α × List α)

full_name: List.mapIdx.go
code: /--
Given a function `f : Nat → α → β` and `as : list α`, `as = [a₀, a₁, ...]`, returns the list
`[f 0 a₀, f 1 a₁, ...]`.
-/
@[inline] def mapIdx (f : Nat → α → β) (as : List α) : List β 
goal: List α → Array β → List β

full_name: List.mapIdx
code: /--
Given a function `f : Nat → α → β` and `as : list α`, `as = [a₀, a₁, ...]`, returns the list
`[f 0 a₀, f 1 a₁, ...]`.
-/
@[inline] def mapIdx (f : Nat → α → β) (as : List α) : List β 
goal: List β

full_name: List.mapIdxM
code: /-- Monadic variant of `mapIdx`. -/
@[inline] def mapIdxM {m : Type v → Type w} [Monad m]
    (as : List α) (f : Nat → α → m β) : m (List β) 
goal: m (List β)

full_name: List.mapIdxM.go
code: /-- Monadic variant of `mapIdx`. -/
@[inline] def mapIdxM {m : Type v → Type w} [Monad m]
    (as : List α) (f : Nat → α → m β) : m (List β) 
goal: List α → Array β → m (List β)

full_name: List.after
code: /--
`after p xs` is the suffix of `xs` after the first element that satisfies
`p`, not including that element.
```lean
after      (· == 1) [0, 1, 2, 3] = [2, 3]
drop_while (· != 1) [0, 1, 2, 3] = [1, 2, 3]
```
-/
@[specialize] def after (p : α → Bool) : List α → List α
  
goal: List α → List α

full_name: List.findIdx.go
code: /-- Returns the index of the first element satisfying `p`, or the length of the list otherwise. -/
@[inline] def findIdx (p : α → Bool) (l : List α) : Nat 
goal: List α → Nat → Nat

full_name: List.findIdx
code: /-- Returns the index of the first element satisfying `p`, or the length of the list otherwise. -/
@[inline] def findIdx (p : α → Bool) (l : List α) : Nat 
goal: Nat

full_name: List.indexOf
code: /-- Returns the index of the first element equal to `a`, or the length of the list otherwise. -/
def indexOf [BEq α] (a : α) : List α → Nat 
goal: List α → Nat

full_name: List.replaceF
code: /-- Replaces the first element of the list for which `f` returns `some` with the returned value. -/
@[simp] def replaceF (f : α → Option α) : List α → List α
  
goal: List α → List α

full_name: List.replaceFTR.go
code: /-- Tail-recursive version of `replaceF`. -/
@[inline] def replaceFTR (f : α → Option α) (l : List α) : List α 
goal: List α → Array α → List α

full_name: List.replaceFTR
code: /-- Tail-recursive version of `replaceF`. -/
@[inline] def replaceFTR (f : α → Option α) (l : List α) : List α 
goal: List α

full_name: List.replaceF_eq_replaceFTR.go
code: @[csimp] theorem replaceF_eq_replaceFTR : @replaceF = @replaceFTR 
goal: List.replaceFTR.go p xs acc = acc.data ++ List.replaceF p xs

full_name: List.replaceF_eq_replaceFTR
code: @[csimp] theorem replaceF_eq_replaceFTR : @replaceF = @replaceFTR 
goal: @List.replaceF = @List.replaceFTR

full_name: List.union
code: /--
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).
-/
@[inline] protected def union [BEq α] (l₁ l₂ : List α) : List α 
goal: List α

full_name: List.«instUnionOfBEq_.lake»
code: instance [BEq α] : Union (List α) 
goal: Union (List α)

full_name: List.inter
code: /--
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]`.
-/
@[inline] protected def inter [BEq α] (l₁ l₂ : List α) : List α 
goal: List α

full_name: List.«instInterOfBEq_.lake»
code: instance [BEq α] : Inter (List α) 
goal: Inter (List α)

full_name: List.Sublist.slnil
code: /-- `l₁ <+ l₂`, or `Sublist l₁ l₂`, says that `l₁` is a (non-contiguous) subsequence of `l₂`. -/
inductive Sublist {α} : List α → List α → Prop
  /-- the base case: `[]` is a sublist of `[]` -/
  | slnil : Sublist [] []
  /-- If `l₁` is a subsequence of `l₂`, then it is also a subsequence of `a :: l₂`. -/
  | cons a : Sublist l₁ l₂ → Sublist l₁ (a :: l₂)
  /-- If `l₁` is a subsequence of `l₂`, then `a :: l₁` is a subsequence of `a :: l₂`. -/
  | cons₂ a : Sublist l₁ l₂ → Sublist (a :: l₁) (a :: l₂)
goal: [] <+ []

full_name: List.Sublist.cons
code: /-- `l₁ <+ l₂`, or `Sublist l₁ l₂`, says that `l₁` is a (non-contiguous) subsequence of `l₂`. -/
inductive Sublist {α} : List α → List α → Prop
  /-- the base case: `[]` is a sublist of `[]` -/
  | slnil : Sublist [] []
  /-- If `l₁` is a subsequence of `l₂`, then it is also a subsequence of `a :: l₂`. -/
  | cons a : Sublist l₁ l₂ → Sublist l₁ (a :: l₂)
  /-- If `l₁` is a subsequence of `l₂`, then `a :: l₁` is a subsequence of `a :: l₂`. -/
  | cons₂ a : Sublist l₁ l₂ → Sublist (a :: l₁) (a :: l₂)
goal: l₁ <+ l₂ → l₁ <+ a :: l₂

full_name: List.Sublist
code: /-- `l₁ <+ l₂`, or `Sublist l₁ l₂`, says that `l₁` is a (non-contiguous) subsequence of `l₂`. -/
inductive Sublist {α} : List α → List α → Prop
  /-- the base case: `[]` is a sublist of `[]` -/
  | slnil : Sublist [] []
  /-- If `l₁` is a subsequence of `l₂`, then it is also a subsequence of `a :: l₂`. -/
  | cons a : Sublist l₁ l₂ → Sublist l₁ (a :: l₂)
  /-- If `l₁` is a subsequence of `l₂`, then `a :: l₁` is a subsequence of `a :: l₂`. -/
  | cons₂ a : Sublist l₁ l₂ → Sublist (a :: l₁) (a :: l₂)
goal: List α → List α → Prop

full_name: List.Sublist.cons₂
code: /-- `l₁ <+ l₂`, or `Sublist l₁ l₂`, says that `l₁` is a (non-contiguous) subsequence of `l₂`. -/
inductive Sublist {α} : List α → List α → Prop
  /-- the base case: `[]` is a sublist of `[]` -/
  | slnil : Sublist [] []
  /-- If `l₁` is a subsequence of `l₂`, then it is also a subsequence of `a :: l₂`. -/
  | cons a : Sublist l₁ l₂ → Sublist l₁ (a :: l₂)
  /-- If `l₁` is a subsequence of `l₂`, then `a :: l₁` is a subsequence of `a :: l₂`. -/
  | cons₂ a : Sublist l₁ l₂ → Sublist (a :: l₁) (a :: l₂)
goal: l₁ <+ l₂ → a :: l₁ <+ a :: l₂

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___unexpand_List_Sublist_1»
code: @[inherit_doc] scoped infixl:50 " <+ " => Sublist
goal: Lean.PrettyPrinter.Unexpander

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___macroRules_List_term_<+__1»
code: @[inherit_doc] scoped infixl:50 " <+ " => Sublist
goal: Lean.Macro

full_name: List.isSublist
code: /-- True if the first list is a potentially non-contiguous sub-sequence of the second list. -/
def isSublist [BEq α] : List α → List α → Bool
  
goal: List α → List α → Bool

full_name: List.splitAt
code: /--
Split a list at an index.
```
splitAt 2 [a, b, c] = ([a, b], [c])
```
-/
def splitAt (n : Nat) (l : List α) : List α × List α 
goal: List α × List α

full_name: List.splitAt.go
code: /--
Split a list at an index.
```
splitAt 2 [a, b, c] = ([a, b], [c])
```
-/
def splitAt (n : Nat) (l : List α) : List α × List α 
goal: List α → Nat → Array α → List α × List α

full_name: List.splitAtD
code: /--
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], [])
```
-/
def splitAtD (n : Nat) (l : List α) (dflt : α) : List α × List α 
goal: List α × List α

full_name: List.splitAtD.go
code: /--
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], [])
```
-/
def splitAtD (n : Nat) (l : List α) (dflt : α) : List α × List α 
goal: Nat → List α → Array α → List α × List α

full_name: List.splitOnP
code: /--
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]]
```
-/
def splitOnP (P : α → Bool) (l : List α) : List (List α) 
goal: List (List α)

full_name: List.splitOnP.go
code: /--
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]]
```
-/
def splitOnP (P : α → Bool) (l : List α) : List (List α) 
goal: List α → List α → List (List α)

full_name: List.splitOnPTR.go
code: /-- Tail recursive version of `splitOnP`. -/
@[inline] def splitOnPTR (P : α → Bool) (l : List α) : List (List α) 
goal: List α → Array α → Array (List α) → List (List α)

full_name: List.splitOnPTR
code: /-- Tail recursive version of `splitOnP`. -/
@[inline] def splitOnPTR (P : α → Bool) (l : List α) : List (List α) 
goal: List (List α)

full_name: List.splitOnP_eq_splitOnPTR
code: @[csimp] theorem splitOnP_eq_splitOnPTR : @splitOnP = @splitOnPTR 
goal: @List.splitOnP = @List.splitOnPTR

full_name: List.splitOn
code: /--
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]]
```
-/
@[inline] def splitOn [BEq α] (a : α) (as : List α) : List (List α) 
goal: List (List α)

full_name: List.modifyNthTail
code: /--
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.
```
modifyNthTail f 2 [a, b, c] = [a, b] ++ f [c]
```
-/
@[simp] def modifyNthTail (f : List α → List α) : Nat → List α → List α
  
goal: Nat → List α → List α

full_name: List.modifyHead
code: /-- Apply `f` to the head of the list, if it exists. -/
@[inline] def modifyHead (f : α → α) : List α → List α
  
goal: List α → List α

full_name: List.modifyHead_nil
code: @[simp] theorem modifyHead_nil (f : α → α) : [].modifyHead f = [] 
goal: List.modifyHead f [] = []

full_name: List.modifyHead_cons
code: @[simp] theorem modifyHead_cons (a : α) (l : List α) (f : α → α) :
    (a :: l).modifyHead f = f a :: l 
goal: List.modifyHead f (a :: l) = f a :: l

full_name: List.modifyNth
code: /-- Apply `f` to the nth element of the list, if it exists. -/
def modifyNth (f : α → α) : Nat → List α → List α 
goal: Nat → List α → List α

full_name: List.modifyNthTR.go
code: /-- Tail-recursive version of `modifyNth`. -/
def modifyNthTR (f : α → α) (n : Nat) (l : List α) : List α 
goal: List α → Nat → Array α → List α

full_name: List.modifyNthTR
code: /-- Tail-recursive version of `modifyNth`. -/
def modifyNthTR (f : α → α) (n : Nat) (l : List α) : List α 
goal: List α

full_name: List.modifyNthTR_go_eq
code: theorem modifyNthTR_go_eq : ∀ l n, modifyNthTR.go f l n acc = acc.data ++ modifyNth f n l
  
goal: ∀ {α : Type u_1} {f : α → α} {acc : Array α} (l : List α) (n : Nat),
  List.modifyNthTR.go f l n acc = acc.data ++ List.modifyNth f n l

full_name: List.modifyNth_eq_modifyNthTR
code: @[csimp] theorem modifyNth_eq_modifyNthTR : @modifyNth = @modifyNthTR 
goal: @List.modifyNth = @List.modifyNthTR

full_name: List.modifyLast.go
code: /-- Apply `f` to the last element of `l`, if it exists. -/
@[inline] def modifyLast (f : α → α) (l : List α) : List α 
goal: List α → Array α → List α

full_name: List.modifyLast
code: /-- Apply `f` to the last element of `l`, if it exists. -/
@[inline] def modifyLast (f : α → α) (l : List α) : List α 
goal: List α

full_name: List.insertNth
code: /--
`insertNth n a l` inserts `a` into the list `l` after the first `n` elements of `l`
```
insertNth 2 1 [1, 2, 3, 4] = [1, 2, 1, 3, 4]
```
-/
def insertNth (n : Nat) (a : α) : List α → List α 
goal: List α → List α

full_name: List.insertNthTR.go
code: /-- Tail-recursive version of `insertNth`. -/
@[inline] def insertNthTR (n : Nat) (a : α) (l : List α) : List α 
goal: Nat → List α → Array α → List α

full_name: List.insertNthTR
code: /-- Tail-recursive version of `insertNth`. -/
@[inline] def insertNthTR (n : Nat) (a : α) (l : List α) : List α 
goal: List α

full_name: List.insertNthTR_go_eq
code: theorem insertNthTR_go_eq : ∀ n l, insertNthTR.go a n l acc = acc.data ++ insertNth n a l
  
goal: ∀ {α : Type u_1} {a : α} {acc : Array α} (n : Nat) (l : List α),
  List.insertNthTR.go a n l acc = acc.data ++ List.insertNth n a l

full_name: List.insertNth_eq_insertNthTR
code: @[csimp] theorem insertNth_eq_insertNthTR : @insertNth = @insertNthTR 
goal: @List.insertNth = @List.insertNthTR

full_name: List.headD_eq_head?
code: @[simp] theorem headD_eq_head? (l) (a : α) : headD l a = (head? l).getD a 
goal: l.headD a = l.head?.getD a

full_name: List.takeD
code: /--
Take `n` elements from a list `l`. If `l` has less than `n` elements, append `n - length l`
elements `x`.
-/
def takeD : Nat → List α → α → List α
  
goal: Nat → List α → α → List α

full_name: List.takeD_zero
code: @[simp] theorem takeD_zero (l) (a : α) : takeD 0 l a = [] 
goal: List.takeD 0 l a = []

full_name: List.takeD_succ
code: @[simp] theorem takeD_succ (l) (a : α) :
    takeD (n+1) l a = l.head?.getD a :: takeD n l.tail a 
goal: List.takeD (n + 1) l a = l.head?.getD a :: List.takeD n l.tail a

full_name: List.takeD_nil
code: @[simp] theorem takeD_nil (n) (a : α) : takeD n [] a = replicate n a 
goal: List.takeD n [] a = List.replicate n a

full_name: List.takeDTR.go
code: /-- Tail-recursive version of `takeD`. -/
def takeDTR (n : Nat) (l : List α) (dflt : α) : List α 
goal: Nat → List α → Array α → List α

full_name: List.takeDTR
code: /-- Tail-recursive version of `takeD`. -/
def takeDTR (n : Nat) (l : List α) (dflt : α) : List α 
goal: List α

full_name: List.takeDTR_go_eq
code: theorem takeDTR_go_eq : ∀ n l, takeDTR.go dflt n l acc = acc.data ++ takeD n l dflt
  
goal: ∀ {α : Type u_1} {dflt : α} {acc : Array α} (n : Nat) (l : List α),
  List.takeDTR.go dflt n l acc = acc.data ++ List.takeD n l dflt

full_name: List.takeD_eq_takeDTR
code: @[csimp] theorem takeD_eq_takeDTR : @takeD = @takeDTR 
goal: @List.takeD = @List.takeDTR

full_name: List.leftpad
code: /--
Pads `l : List α` with repeated occurrences of `a : α` until it is of length `n`.
If `l` is initially larger than `n`, just return `l`.
-/
def leftpad (n : Nat) (a : α) (l : List α) : List α 
goal: List α

full_name: List.leftpadTR
code: /-- Optimized version of `leftpad`. -/
@[inline] def leftpadTR (n : Nat) (a : α) (l : List α) : List α 
goal: List α

full_name: List.leftpad_eq_leftpadTR
code: @[csimp] theorem leftpad_eq_leftpadTR : @leftpad = @leftpadTR 
goal: @List.leftpad = @List.leftpadTR

full_name: List.scanl
code: /--
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]
```
-/
@[simp] def scanl (f : α → β → α) (a : α) : List β → List α
  
goal: List β → List α

full_name: List.scanlTR
code: /-- Tail-recursive version of `scanl`. -/
@[inline] def scanlTR (f : α → β → α) (a : α) (l : List β) : List α 
goal: List α

full_name: List.scanlTR.go
code: /-- Tail-recursive version of `scanl`. -/
@[inline] def scanlTR (f : α → β → α) (a : α) (l : List β) : List α 
goal: List β → α → Array α → List α

full_name: List.scanlTR_go_eq
code: theorem scanlTR_go_eq : ∀ l, scanlTR.go f l a acc = acc.data ++ scanl f a l
  
goal: ∀ {α : Type u_1} {α_1 : Type u_2} {f : α → α_1 → α} {a : α} {acc : Array α} (l : List α_1),
  List.scanlTR.go f l a acc = acc.data ++ List.scanl f a l

full_name: List.scanl_eq_scanlTR
code: @[csimp] theorem scanl_eq_scanlTR : @scanl = @scanlTR 
goal: @List.scanl = @List.scanlTR

full_name: List.scanr
code: /--
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]
```
-/
def scanr (f : α → β → β) (b : β) (l : List α) : List β 
goal: List β

full_name: List.foldlIdx
code: /--
Fold a list from left to right as with `foldl`, but the combining function
also receives each element's index.
-/
@[simp, specialize] def foldlIdx (f : Nat → α → β → α) (init : α) : List β → (start : _ := 0) → α
  
goal: List β → optParam Nat 0 → α

full_name: List.foldrIdx
code: /--
Fold a list from right to left as with `foldr`, but the combining function
also receives each element's index.
-/
-- TODO(Mario): tail recursive / array-based implementation
@[simp, specialize] def foldrIdx (f : Nat → α → β → β) (init : β) :
    (l : List α) → (start : _ := 0) → β
  
goal: β

full_name: List.findIdxs
code: /-- `findIdxs p l` is the list of indexes of elements of `l` that satisfy `p`. -/
@[inline] def findIdxs (p : α → Bool) (l : List α) : List Nat 
goal: List Nat

full_name: List.indexesValues
code: /--
Returns the elements of `l` that satisfy `p` together with their indexes in
`l`. The returned list is ordered by index.
-/
@[inline] def indexesValues (p : α → Bool) (l : List α) : List (Nat × α) 
goal: List (Nat × α)

full_name: List.indexesOf
code: /--
`indexesOf a l` is the list of all indexes of `a` in `l`. For example:
```
indexesOf a [a, b, a, a] = [0, 2, 3]
```
-/
@[inline] def indexesOf [BEq α] (a : α) : List α → List Nat 
goal: List α → List Nat

full_name: List.findIdx?
code: /-- Return the index of the first occurrence of an element satisfying `p`. -/
def findIdx? (p : α → Bool) : List α → (start : Nat := 0) → Option Nat

goal: List α → optParam Nat 0 → Option Nat

full_name: List.indexOf?
code: /-- Return the index of the first occurrence of `a` in the list. -/
@[inline] def indexOf? [BEq α] (a : α) : List α → Option Nat 
goal: List α → Option Nat

full_name: List.lookmap.go
code: /--
`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`.
-/
@[inline] def lookmap (f : α → Option α) (l : List α) : List α 
goal: List α → Array α → List α

full_name: List.lookmap
code: /--
`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`.
-/
@[inline] def lookmap (f : α → Option α) (l : List α) : List α 
goal: List α

full_name: List.countP
code: /-- `countP p l` is the number of elements of `l` that satisfy `p`. -/
@[inline] def countP (p : α → Bool) (l : List α) : Nat 
goal: Nat

full_name: List.countP.go
code: /-- `countP p l` is the number of elements of `l` that satisfy `p`. -/
@[inline] def countP (p : α → Bool) (l : List α) : Nat 
goal: List α → Nat → Nat

full_name: List.count
code: /-- `count a l` is the number of occurrences of `a` in `l`. -/
@[inline] def count [BEq α] (a : α) : List α → Nat 
goal: List α → Nat

full_name: List.IsPrefix
code: /--
`IsPrefix l₁ l₂`, or `l₁ <+: l₂`, means that `l₁` is a prefix of `l₂`,
that is, `l₂` has the form `l₁ ++ t` for some `t`.
-/
def IsPrefix (l₁ : List α) (l₂ : List α) : Prop 
goal: Prop

full_name: List.IsSuffix
code: /--
`IsSuffix l₁ l₂`, or `l₁ <:+ l₂`, means that `l₁` is a suffix of `l₂`,
that is, `l₂` has the form `t ++ l₁` for some `t`.
-/
def IsSuffix (l₁ : List α) (l₂ : List α) : Prop 
goal: Prop

full_name: List.IsInfix
code: /--
`IsInfix l₁ l₂`, or `l₁ <:+: l₂`, means that `l₁` is a contiguous
substring of `l₂`, that is, `l₂` has the form `s ++ l₁ ++ t` for some `s, t`.
-/
def IsInfix (l₁ : List α) (l₂ : List α) : Prop 
goal: Prop

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___unexpand_List_IsPrefix_1»
code: @[inherit_doc] infixl:50 " <+: " => IsPrefix
goal: Lean.PrettyPrinter.Unexpander

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___macroRules_List_term_<+:__1»
code: @[inherit_doc] infixl:50 " <+: " => IsPrefix
goal: Lean.Macro

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___unexpand_List_IsSuffix_1»
code: @[inherit_doc] infixl:50 " <:+ " => IsSuffix
goal: Lean.PrettyPrinter.Unexpander

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___macroRules_List_term_<:+__1»
code: @[inherit_doc] infixl:50 " <:+ " => IsSuffix
goal: Lean.Macro

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___macroRules_List_term_<:+:__1»
code: @[inherit_doc] infixl:50 " <:+: " => IsInfix
goal: Lean.Macro

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___unexpand_List_IsInfix_1»
code: @[inherit_doc] infixl:50 " <:+: " => IsInfix
goal: Lean.PrettyPrinter.Unexpander

full_name: List.inits
code: /--
`inits l` is the list of initial segments of `l`.
```
inits [1, 2, 3] = [[], [1], [1, 2], [1, 2, 3]]
```
-/
@[simp] def inits : List α → List (List α)
  
goal: List α → List (List α)

full_name: List.initsTR
code: /-- Tail-recursive version of `inits`. -/
def initsTR (l : List α) : List (List α) 
goal: List (List α)

full_name: List.inits_eq_initsTR
code: @[csimp] theorem inits_eq_initsTR : @inits = @initsTR 
goal: @List.inits = @List.initsTR

full_name: List.tails
code: /--
`tails l` is the list of terminal segments of `l`.
```
tails [1, 2, 3] = [[1, 2, 3], [2, 3], [3], []]
```
-/
@[simp] def tails : List α → List (List α)
  
goal: List α → List (List α)

full_name: List.tailsTR
code: /-- Tail-recursive version of `tails`. -/
def tailsTR (l : List α) : List (List α) 
goal: List (List α)

full_name: List.tailsTR.go
code: /-- Tail-recursive version of `tails`. -/
def tailsTR (l : List α) : List (List α) 
goal: List (List α)

full_name: List.tails_eq_tailsTR
code: @[csimp] theorem tails_eq_tailsTR : @tails = @tailsTR 
goal: @List.tails = @List.tailsTR

full_name: List.sublists'
code: /--
`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]]
```
-/
def sublists' (l : List α) : List (List α) 
goal: List (List α)

full_name: List.sublists
code: /--
`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]]
```
-/
def sublists (l : List α) : List (List α) 
goal: List (List α)

full_name: List.sublistsFast
code: /-- A version of `List.sublists` that has faster runtime performance but worse kernel performance -/
def sublistsFast (l : List α) : List (List α) 
goal: List (List α)

full_name: List.Forall₂
code: /--
`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.
-/
inductive Forall₂ (R : α → β → Prop) : List α → List β → Prop
  /-- Two nil lists are `Forall₂`-related -/
  | nil : Forall₂ R [] []
  /-- Two cons lists are related by `Forall₂ R`
  if the heads are related by `R` and the tails are related by `Forall₂ R` -/
  | cons {a b l₁ l₂} : R a b → Forall₂ R l₁ l₂ → Forall₂ R (a :: l₁) (b :: l₂)
goal: List α → List β → Prop

full_name: List.Forall₂.cons
code: /--
`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.
-/
inductive Forall₂ (R : α → β → Prop) : List α → List β → Prop
  /-- Two nil lists are `Forall₂`-related -/
  | nil : Forall₂ R [] []
  /-- Two cons lists are related by `Forall₂ R`
  if the heads are related by `R` and the tails are related by `Forall₂ R` -/
  | cons {a b l₁ l₂} : R a b → Forall₂ R l₁ l₂ → Forall₂ R (a :: l₁) (b :: l₂)
goal: R a b → List.Forall₂ R l₁ l₂ → List.Forall₂ R (a :: l₁) (b :: l₂)

full_name: List.Forall₂.nil
code: /--
`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.
-/
inductive Forall₂ (R : α → β → Prop) : List α → List β → Prop
  /-- Two nil lists are `Forall₂`-related -/
  | nil : Forall₂ R [] []
  /-- Two cons lists are related by `Forall₂ R`
  if the heads are related by `R` and the tails are related by `Forall₂ R` -/
  | cons {a b l₁ l₂} : R a b → Forall₂ R l₁ l₂ → Forall₂ R (a :: l₁) (b :: l₂)
goal: List.Forall₂ R [] []

full_name: List.forall₂_cons
code: @[simp] theorem forall₂_cons {R : α → β → Prop} {a b l₁ l₂} :
    Forall₂ R (a :: l₁) (b :: l₂) ↔ R a b ∧ Forall₂ R l₁ l₂ 
goal: List.Forall₂ R (a :: l₁) (b :: l₂) ↔ R a b ∧ List.Forall₂ R l₁ l₂

full_name: List.all₂
code: /--
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`.
-/
def all₂ (r : α → β → Bool) : List α → List β → Bool
  
goal: List α → List β → Bool

full_name: List.all₂_eq_true
code: @[simp] theorem all₂_eq_true {r : α → β → Bool} :
    ∀ l₁ l₂, all₂ r l₁ l₂ ↔ Forall₂ (r · ·) l₁ l₂
  
goal: List.all₂ r l₁ l₂ = true ↔ List.Forall₂ (fun x x_1 => r x x_1 = true) l₁ l₂

full_name: List.instDecidableForall₂
code: instance {R : α → β → Prop} [∀ a b, Decidable (R a b)] : ∀ l₁ l₂, Decidable (Forall₂ R l₁ l₂) 
goal: Decidable (List.Forall₂ R l₁ l₂)

full_name: List.transpose.pop
code: /--
Transpose of a list of lists, treated as a matrix.
```
transpose [[1, 2], [3, 4], [5, 6]] = [[1, 3, 5], [2, 4, 6]]
```
-/
def transpose (l : List (List α)) : List (List α) 
goal: List α → Id (List α × List α)

full_name: List.transpose
code: /--
Transpose of a list of lists, treated as a matrix.
```
transpose [[1, 2], [3, 4], [5, 6]] = [[1, 3, 5], [2, 4, 6]]
```
-/
def transpose (l : List (List α)) : List (List α) 
goal: List (List α)

full_name: List.transpose.go
code: /--
Transpose of a list of lists, treated as a matrix.
```
transpose [[1, 2], [3, 4], [5, 6]] = [[1, 3, 5], [2, 4, 6]]
```
-/
def transpose (l : List (List α)) : List (List α) 
goal: Array (List α)

full_name: List.sections
code: /--
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.
-/
@[simp] def sections : List (List α) → List (List α)
  
goal: List (List α) → List (List α)

full_name: List.sectionsTR
code: /-- Optimized version of `sections`. -/
def sectionsTR (L : List (List α)) : List (List α) 
goal: List (List α)

full_name: List.sectionsTR.go
code: /-- Optimized version of `sections`. -/
def sectionsTR (L : List (List α)) : List (List α) 
goal: Array (List α)

full_name: List.sections_eq_nil_of_isEmpty
code: theorem sections_eq_nil_of_isEmpty : ∀ {L}, L.any isEmpty → @sections α L = []
  
goal: L.any List.isEmpty = true → L.sections = []

full_name: List.sections_eq_sectionsTR
code: @[csimp] theorem sections_eq_sectionsTR : @sections = @sectionsTR 
goal: @List.sections = @List.sectionsTR

full_name: List.eraseP
code: /-- `eraseP p l` removes the first element of `l` satisfying the predicate `p`. -/
def eraseP (p : α → Bool) : List α → List α
  
goal: List α → List α

full_name: List.erasePTR.go
code: /-- Tail-recursive version of `eraseP`. -/
@[inline] def erasePTR (p : α → Bool) (l : List α) : List α 
goal: List α → Array α → List α

full_name: List.erasePTR
code: /-- Tail-recursive version of `eraseP`. -/
@[inline] def erasePTR (p : α → Bool) (l : List α) : List α 
goal: List α

full_name: List.eraseP_eq_erasePTR.go
code: @[csimp] theorem eraseP_eq_erasePTR : @eraseP = @erasePTR 
goal: l = acc.data ++ xs → List.erasePTR.go p l xs acc = acc.data ++ List.eraseP p xs

full_name: List.eraseP_eq_erasePTR
code: @[csimp] theorem eraseP_eq_erasePTR : @eraseP = @erasePTR 
goal: @List.eraseP = @List.erasePTR

full_name: List.extractP.go
code: /--
`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)`.
-/
def extractP (p : α → Bool) (l : List α) : Option α × List α 
goal: List α → Array α → Option α × List α

full_name: List.extractP
code: /--
`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)`.
-/
def extractP (p : α → Bool) (l : List α) : Option α × List α 
goal: Option α × List α

full_name: List.revzip
code: /--
`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)]
```
-/
def revzip (l : List α) : List (α × α) 
goal: List (α × α)

full_name: List.product
code: /--
`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)]
```
-/
def product (l₁ : List α) (l₂ : List β) : List (α × β) 
goal: List (α × β)

full_name: List.productTR
code: /-- Optimized version of `product`. -/
def productTR (l₁ : List α) (l₂ : List β) : List (α × β) 
goal: List (α × β)

full_name: List.product_eq_productTR
code: @[csimp] theorem product_eq_productTR : @product = @productTR 
goal: @List.product = @List.productTR

full_name: List.sigma
code: /-- `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)]
``` -/
protected def sigma {σ : α → Type _} (l₁ : List α) (l₂ : ∀ a, List (σ a)) : List (Σ a, σ a) 
goal: List ((a : α) × σ a)

full_name: List.sigmaTR
code: /-- Optimized version of `sigma`. -/
def sigmaTR {σ : α → Type _} (l₁ : List α) (l₂ : ∀ a, List (σ a)) : List (Σ a, σ a) 
goal: List ((a : α) × σ a)

full_name: List.sigma_eq_sigmaTR
code: @[csimp] theorem sigma_eq_sigmaTR : @List.sigma = @sigmaTR 
goal: @List.sigma = @List.sigmaTR

full_name: List.ofFn
code: /--
`ofFn f` with `f : fin n → α` returns the list whose ith element is `f i`
```
ofFn f = [f 0, f 1, ... , f (n - 1)]
```
-/
def ofFn {n} (f : Fin n → α) : List α 
goal: List α

full_name: List.ofFn.go
code: /--
`ofFn f` with `f : fin n → α` returns the list whose ith element is `f i`
```
ofFn f = [f 0, f 1, ... , f (n - 1)]
```
-/
def ofFn {n} (f : Fin n → α) : List α 
goal: List α

full_name: List.ofFnTR.go
code: /-- Tail-recursive version of `ofFn`. -/
@[inline] def ofFnTR {n} (f : Fin n → α) : List α 
goal: List α → List α

full_name: List.ofFnTR
code: /-- Tail-recursive version of `ofFn`. -/
@[inline] def ofFnTR {n} (f : Fin n → α) : List α 
goal: List α

full_name: List.ofFn_eq_ofFnTR.go
code: @[csimp] theorem ofFn_eq_ofFnTR : @ofFn = @ofFnTR 
goal: List.ofFnTR.go f j h' (List.ofFn.go f i j h) = List.ofFn f

full_name: List.ofFn_eq_ofFnTR
code: @[csimp] theorem ofFn_eq_ofFnTR : @ofFn = @ofFnTR 
goal: @List.ofFn = @List.ofFnTR

full_name: List.ofFnNthVal
code: /-- `ofFnNthVal f i` returns `some (f i)` if `i < n` and `none` otherwise. -/
def ofFnNthVal {n} (f : Fin n → α) (i : Nat) : Option α 
goal: Option α

full_name: List.Disjoint
code: /-- `disjoint l₁ l₂` means that `l₁` and `l₂` have no elements in common. -/
def Disjoint (l₁ l₂ : List α) : Prop 
goal: Prop

full_name: List.takeWhile₂
code: /--
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])
```
-/
def takeWhile₂ (R : α → β → Bool) : List α → List β → List α × List β
  
goal: List α → List β → List α × List β

full_name: List.takeWhile₂TR
code: /-- Tail-recursive version of `takeWhile₂`. -/
@[inline] def takeWhile₂TR (R : α → β → Bool) (as : List α) (bs : List β) : List α × List β 
goal: List α × List β

full_name: List.takeWhile₂TR.go
code: /-- Tail-recursive version of `takeWhile₂`. -/
@[inline] def takeWhile₂TR (R : α → β → Bool) (as : List α) (bs : List β) : List α × List β 
goal: List α → List β → List α → List β → List α × List β

full_name: List.takeWhile₂_eq_takeWhile₂TR
code: @[csimp] theorem takeWhile₂_eq_takeWhile₂TR : @takeWhile₂ = @takeWhile₂TR 
goal: @List.takeWhile₂ = @List.takeWhile₂TR

full_name: List.takeWhile₂_eq_takeWhile₂TR.go
code: @[csimp] theorem takeWhile₂_eq_takeWhile₂TR : @takeWhile₂ = @takeWhile₂TR 
goal: List.takeWhile₂TR.go R as bs acca accb =
  (acca.reverse ++ (List.takeWhile₂ R as bs).fst, accb.reverse ++ (List.takeWhile₂ R as bs).snd)

full_name: List.Pairwise.nil
code: /--
`Pairwise R l` means that all the elements with earlier indexes are
`R`-related to all the elements with later indexes.
```
Pairwise R [1, 2, 3] ↔ R 1 2 ∧ R 1 3 ∧ R 2 3
```
For example if `R = (·≠·)` then it asserts `l` has no duplicates,
and if `R = (·<·)` then it asserts that `l` is (strictly) sorted.
-/
inductive Pairwise : List α → Prop
  /-- All elements of the empty list are vacuously pairwise related. -/
  | nil : Pairwise []
  /-- `a :: l` is `Pairwise R` if `a` `R`-relates to every element of `l`,
  and `l` is `Pairwise R`. -/
  | cons : ∀ {a : α} {l : List α}, (∀ a' ∈ l, R a a') → Pairwise l → Pairwise (a :: l)
goal: List.Pairwise R []

full_name: List.Pairwise.cons
code: /--
`Pairwise R l` means that all the elements with earlier indexes are
`R`-related to all the elements with later indexes.
```
Pairwise R [1, 2, 3] ↔ R 1 2 ∧ R 1 3 ∧ R 2 3
```
For example if `R = (·≠·)` then it asserts `l` has no duplicates,
and if `R = (·<·)` then it asserts that `l` is (strictly) sorted.
-/
inductive Pairwise : List α → Prop
  /-- All elements of the empty list are vacuously pairwise related. -/
  | nil : Pairwise []
  /-- `a :: l` is `Pairwise R` if `a` `R`-relates to every element of `l`,
  and `l` is `Pairwise R`. -/
  | cons : ∀ {a : α} {l : List α}, (∀ a' ∈ l, R a a') → Pairwise l → Pairwise (a :: l)
goal: (∀ (a' : α), a' ∈ l → R a a') → List.Pairwise R l → List.Pairwise R (a :: l)

full_name: List.Pairwise
code: /--
`Pairwise R l` means that all the elements with earlier indexes are
`R`-related to all the elements with later indexes.
```
Pairwise R [1, 2, 3] ↔ R 1 2 ∧ R 1 3 ∧ R 2 3
```
For example if `R = (·≠·)` then it asserts `l` has no duplicates,
and if `R = (·<·)` then it asserts that `l` is (strictly) sorted.
-/
inductive Pairwise : List α → Prop
  /-- All elements of the empty list are vacuously pairwise related. -/
  | nil : Pairwise []
  /-- `a :: l` is `Pairwise R` if `a` `R`-relates to every element of `l`,
  and `l` is `Pairwise R`. -/
  | cons : ∀ {a : α} {l : List α}, (∀ a' ∈ l, R a a') → Pairwise l → Pairwise (a :: l)
goal: List α → Prop

full_name: List.pairwise_cons
code: @[simp] theorem pairwise_cons : Pairwise R (a::l) ↔ (∀ a' ∈ l, R a a') ∧ Pairwise R l 
goal: List.Pairwise R (a :: l) ↔ (∀ (a' : α), a' ∈ l → R a a') ∧ List.Pairwise R l

full_name: List.instDecidablePairwise
code: instance instDecidablePairwise [DecidableRel R] :
    (l : List α) → Decidable (Pairwise R l)
  
goal: Decidable (List.Pairwise R l)

full_name: List.pwFilter
code: /--
`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]
```
-/
def pwFilter (R : α → α → Prop) [DecidableRel R] (l : List α) : List α 
goal: List α

full_name: List.Chain.nil
code: /-- `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
``` -/
inductive Chain : α → List α → Prop
  /-- A chain of length 1 is trivially a chain. -/
  | nil {a : α} : Chain a []
  /-- If `a` relates to `b` and `b::l` is a chain, then `a :: b :: l` is also a chain. -/
  | cons : ∀ {a b : α} {l : List α}, R a b → Chain b l → Chain a (b :: l)
goal: List.Chain R a []

full_name: List.Chain.cons
code: /-- `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
``` -/
inductive Chain : α → List α → Prop
  /-- A chain of length 1 is trivially a chain. -/
  | nil {a : α} : Chain a []
  /-- If `a` relates to `b` and `b::l` is a chain, then `a :: b :: l` is also a chain. -/
  | cons : ∀ {a b : α} {l : List α}, R a b → Chain b l → Chain a (b :: l)
goal: R a b → List.Chain R b l → List.Chain R a (b :: l)

full_name: List.Chain
code: /-- `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
``` -/
inductive Chain : α → List α → Prop
  /-- A chain of length 1 is trivially a chain. -/
  | nil {a : α} : Chain a []
  /-- If `a` relates to `b` and `b::l` is a chain, then `a :: b :: l` is also a chain. -/
  | cons : ∀ {a b : α} {l : List α}, R a b → Chain b l → Chain a (b :: l)
goal: α → List α → Prop

full_name: List.Chain'
code: /-- `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
``` -/
def Chain' : List α → Prop
  
goal: List α → Prop

full_name: List.Nodup
code: /-- `Nodup l` means that `l` has no duplicates, that is, any element appears at most
  once in the List. It is defined as `Pairwise (≠)`. -/
def Nodup : List α → Prop 
goal: List α → Prop

full_name: List.nodupDecidable
code: instance nodupDecidable [DecidableEq α] : ∀ l : List α, Decidable (Nodup l) 
goal: Decidable l.Nodup

full_name: List.eraseDup
code: /-- `eraseDup l` removes duplicates from `l` (taking only the first occurrence).
Defined as `pwFilter (≠)`.

    eraseDup [1, 0, 2, 2, 1] = [0, 2, 1] -/
@[inline] def eraseDup [BEq α] : List α → List α 
goal: List α → List α

full_name: List.range'
code: /-- `range' start len step` is the list of numbers `[start, start+step, ..., start+(len-1)*step]`.
  It is intended mainly for proving properties of `range` and `iota`. -/
def range' : (start len : Nat) → (step : Nat := 1) → List Nat
  
goal: List Nat

full_name: List.range'TR.go
code: /-- Optimized version of `range'`. -/
@[inline] def range'TR (s n : Nat) (step : Nat := 1) : List Nat 
goal: Nat → Nat → List Nat → List Nat

full_name: List.range'TR
code: /-- Optimized version of `range'`. -/
@[inline] def range'TR (s n : Nat) (step : Nat := 1) : List Nat 
goal: List Nat

full_name: List.range'_eq_range'TR
code: @[csimp] theorem range'_eq_range'TR : @range' = @range'TR 
goal: @List.range' = @List.range'TR

full_name: List.range'_eq_range'TR.go
code: @[csimp] theorem range'_eq_range'TR : @range' = @range'TR 
goal: List.range'TR.go step n (s + step * n) (List.range' (s + step * n) m step) = List.range' s (n + m) step

full_name: List.reduceOption
code: /-- Drop `none`s from a list, and replace each remaining `some a` with `a`. -/
@[inline] def reduceOption {α} : List (Option α) → List α 
goal: List (Option α) → List α

full_name: List.ilast'
code: /--
`ilast' x xs` returns the last element of `xs` if `xs` is non-empty; it returns `x` otherwise.
Use `List.getLastD` instead.
-/
@[simp, deprecated getLastD (since := "2024-01-09")] def ilast' {α} : α → List α → α
  
goal: α → List α → α

full_name: List.last'
code: /--
`last' xs` returns the last element of `xs` if `xs` is non-empty; it returns `none` otherwise.
Use `List.getLast?` instead
-/
@[simp, deprecated getLast? (since := "2024-01-09")] def last' {α} : List α → Option α
  
goal: List α → Option α

full_name: List.rotate
code: /--
`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]
```
-/
@[inline] def rotate (l : List α) (n : Nat) : List α 
goal: List α

full_name: List.rotate'
code: /-- `rotate'` is the same as `rotate`, but slower. Used for proofs about `rotate` -/
@[simp] def rotate' : List α → Nat → List α
  
goal: List α → Nat → List α

full_name: List.mapDiagM.go
code: /--
`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]
```
-/
def mapDiagM [Monad m] (f : α → α → m β) (l : List α) : m (List β) 
goal: List α → Array β → m (List β)

full_name: List.mapDiagM
code: /--
`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]
```
-/
def mapDiagM [Monad m] (f : α → α → m β) (l : List α) : m (List β) 
goal: m (List β)

full_name: List.forDiagM
code: /--
`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
```
-/
@[simp] def forDiagM [Monad m] (f : α → α → m PUnit) : List α → m PUnit
  
goal: List α → m PUnit

full_name: List.getRest
code: /-- `getRest l l₁` returns `some l₂` if `l = l₁ ++ l₂`.
  If `l₁` is not a prefix of `l`, returns `none` -/
def getRest [DecidableEq α] : List α → List α → Option (List α)
  
goal: List α → List α → Option (List α)

full_name: List.dropSlice
code: /-- `List.dropSlice n m xs` removes a slice of length `m` at index `n` in list `xs`. -/
@[simp] def dropSlice : Nat → Nat → List α → List α
  
goal: Nat → Nat → List α → List α

full_name: List.dropSliceTR
code: /-- Optimized version of `dropSlice`. -/
@[inline] def dropSliceTR (n m : Nat) (l : List α) : List α 
goal: List α

full_name: List.dropSliceTR.go
code: /-- Optimized version of `dropSlice`. -/
@[inline] def dropSliceTR (n m : Nat) (l : List α) : List α 
goal: List α → Nat → Array α → List α

full_name: List.dropSlice_zero₂
code: theorem dropSlice_zero₂ : ∀ n l, @dropSlice α n 0 l = l
  
goal: List.dropSlice n 0 l = l

full_name: List.dropSlice_eq_dropSliceTR.go
code: @[csimp] theorem dropSlice_eq_dropSliceTR : @dropSlice = @dropSliceTR 
goal: l = acc.data ++ xs → List.dropSliceTR.go l m xs n acc = acc.data ++ List.dropSlice n (m + 1) xs

full_name: List.dropSlice_eq_dropSliceTR
code: @[csimp] theorem dropSlice_eq_dropSliceTR : @dropSlice = @dropSliceTR 
goal: @List.dropSlice = @List.dropSliceTR

full_name: List.zipWithLeft'
code: /--
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'])
```
-/
@[simp] def zipWithLeft' (f : α → Option β → γ) : List α → List β → List γ × List β
  
goal: List α → List β → List γ × List β

full_name: List.zipWithLeft'TR.go
code: /-- Tail-recursive version of `zipWithLeft'`. -/
@[inline] def zipWithLeft'TR (f : α → Option β → γ)
    (as : List α) (bs : List β) : List γ × List β 
goal: List α → List β → Array γ → List γ × List β

full_name: List.zipWithLeft'TR
code: /-- Tail-recursive version of `zipWithLeft'`. -/
@[inline] def zipWithLeft'TR (f : α → Option β → γ)
    (as : List α) (bs : List β) : List γ × List β 
goal: List γ × List β

full_name: List.zipWithLeft'_eq_zipWithLeft'TR.go
code: @[csimp] theorem zipWithLeft'_eq_zipWithLeft'TR : @zipWithLeft' = @zipWithLeft'TR 
goal: List.zipWithLeft'TR.go f as bs acc =
  match List.zipWithLeft' f as bs with
  | (l, r) => (acc.toList ++ l, r)

full_name: List.zipWithLeft'_eq_zipWithLeft'TR
code: @[csimp] theorem zipWithLeft'_eq_zipWithLeft'TR : @zipWithLeft' = @zipWithLeft'TR 
goal: @List.zipWithLeft' = @List.zipWithLeft'TR

full_name: List.zipWithRight'
code: /--
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])
```
-/
@[inline] def zipWithRight' (f : Option α → β → γ) (as : List α) (bs : List β) : List γ × List α 
goal: List γ × List α

full_name: List.zipLeft'
code: /--
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
```
-/
@[inline] def zipLeft' : List α → List β → List (α × Option β) × List β 
goal: List α → List β → List (α × Option β) × List β

full_name: List.zipRight'
code: /--
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
```
-/
@[inline] def zipRight' : List α → List β → List (Option α × β) × List α 
goal: List α → List β → List (Option α × β) × List α

full_name: List.zipWithLeft
code: /--
Left-biased version of `List.zipWith`. `zipWithLeft f as bs` applies `f` to each pair
`aᵢ ∈ as` and `bᵢ ‌∈ 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
```
-/
@[simp] def zipWithLeft (f : α → Option β → γ) : List α → List β → List γ
  
goal: List α → List β → List γ

full_name: List.zipWithLeftTR
code: /-- Tail-recursive version of `zipWithLeft`. -/
@[inline] def zipWithLeftTR (f : α → Option β → γ)
    (as : List α) (bs : List β) : List γ 
goal: List γ

full_name: List.zipWithLeftTR.go
code: /-- Tail-recursive version of `zipWithLeft`. -/
@[inline] def zipWithLeftTR (f : α → Option β → γ)
    (as : List α) (bs : List β) : List γ 
goal: List α → List β → Array γ → List γ

full_name: List.zipWithLeft_eq_zipWithLeftTR
code: @[csimp] theorem zipWithLeft_eq_zipWithLeftTR : @zipWithLeft = @zipWithLeftTR 
goal: @List.zipWithLeft = @List.zipWithLeftTR

full_name: List.zipWithLeft_eq_zipWithLeftTR.go
code: @[csimp] theorem zipWithLeft_eq_zipWithLeftTR : @zipWithLeft = @zipWithLeftTR 
goal: List.zipWithLeftTR.go f as bs acc = acc.toList ++ List.zipWithLeft f as bs

full_name: List.zipWithRight
code: /--
Right-biased version of `List.zipWith`. `zipWithRight f as bs` applies `f` to each
pair `aᵢ ∈ as` and `bᵢ ‌∈ 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
```
-/
@[inline] def zipWithRight (f : Option α → β → γ) (as : List α) (bs : List β) : List γ 
goal: List γ

full_name: List.zipLeft
code: /--
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
```
-/
@[inline] def zipLeft : List α → List β → List (α × Option β) 
goal: List α → List β → List (α × Option β)

full_name: List.zipRight
code: /--
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
```
-/
@[inline] def zipRight : List α → List β → List (Option α × β) 
goal: List α → List β → List (Option α × β)

full_name: List.allSome
code: /--
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
```
-/
@[inline] def allSome (l : List (Option α)) : Option (List α) 
goal: Option (List α)

full_name: List.fillNones
code: /--
`fillNones xs ys` replaces the `none`s in `xs` with elements of `ys`. If there
are not enough `ys` to replace all the `none`s, the remaining `none`s are
dropped from `xs`.
```
fillNones [none, some 1, none, none] [2, 3] = [2, 1, 3]
```
-/
@[simp] def fillNones {α} : List (Option α) → List α → List α
  
goal: List (Option α) → List α → List α

full_name: List.fillNonesTR
code: /-- Tail-recursive version of `fillNones`. -/
@[inline] def fillNonesTR (as : List (Option α)) (as' : List α) : List α 
goal: List α

full_name: List.fillNonesTR.go
code: /-- Tail-recursive version of `fillNones`. -/
@[inline] def fillNonesTR (as : List (Option α)) (as' : List α) : List α 
goal: List (Option α) → List α → Array α → List α

full_name: List.fillNones_eq_fillNonesTR
code: @[csimp] theorem fillNones_eq_fillNonesTR : @fillNones = @fillNonesTR 
goal: @List.fillNones = @List.fillNonesTR

full_name: List.fillNones_eq_fillNonesTR.go
code: @[csimp] theorem fillNones_eq_fillNonesTR : @fillNones = @fillNonesTR 
goal: List.fillNonesTR.go as as' acc = acc.data ++ as.fillNones as'

full_name: List.takeList
code: /--
`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'], []], [])
```
-/
def takeList {α} : List α → List Nat → List (List α) × List α
  
goal: List α → List Nat → List (List α) × List α

full_name: List.takeListTR.go
code: /-- Tail-recursive version of `takeList`. -/
@[inline] def takeListTR
    (xs : List α) (ns : List Nat) : List (List α) × List α 
goal: List Nat → List α → Array (List α) → List (List α) × List α

full_name: List.takeListTR
code: /-- Tail-recursive version of `takeList`. -/
@[inline] def takeListTR
    (xs : List α) (ns : List Nat) : List (List α) × List α 
goal: List (List α) × List α

full_name: List.takeList_eq_takeListTR
code: @[csimp] theorem takeList_eq_takeListTR : @takeList = @takeListTR 
goal: @List.takeList = @List.takeListTR

full_name: List.takeList_eq_takeListTR.go
code: @[csimp] theorem takeList_eq_takeListTR : @takeList = @takeListTR 
goal: List.takeListTR.go ns xs acc =
  match xs.takeList ns with
  | (l, r) => (acc.toList ++ l, r)

full_name: List.toChunksAux
code: /-- 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`. -/
def toChunksAux {α} (n : Nat) : List α → Nat → List α × List (List α)
  
goal: List α → Nat → List α × List (List α)

full_name: List.toChunks
code: /--
`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]]
```
-/
def toChunks {α} : Nat → List α → List (List α)
  
goal: Nat → List α → List (List α)

full_name: List.toChunks.go
code: /--
`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]]
```
-/
def toChunks {α} : Nat → List α → List (List α)
  
goal: List α → Array α → Array (List α) → List (List α)

full_name: List.zipWith₃
code: /-- Ternary version of `List.zipWith`. -/
def zipWith₃ (f : α → β → γ → δ) : List α → List β → List γ → List δ
  
goal: List α → List β → List γ → List δ

full_name: List.zipWith₄
code: /-- Quaternary version of `List.zipWith`. -/
def zipWith₄ (f : α → β → γ → δ → ε) : List α → List β → List γ → List δ → List ε
  
goal: List α → List β → List γ → List δ → List ε

full_name: List.zipWith₅
code: /-- Quinary version of `List.zipWith`. -/
def zipWith₅ (f : α → β → γ → δ → ε → ζ) : List α → List β → List γ → List δ → List ε → List ζ
  
goal: List α → List β → List γ → List δ → List ε → List ζ

full_name: List.mapWithPrefixSuffixAux
code: /-- An auxiliary function for `List.mapWithPrefixSuffix`. -/
-- TODO(Mario): tail recursive
def mapWithPrefixSuffixAux {α β} (f : List α → α → List α → β) : List α → List α → List β
  
goal: List α → List α → List β

full_name: List.mapWithPrefixSuffix
code: /--
`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 Nat → Nat → list Nat → β`,
`List.mapWithPrefixSuffix f [1, 2, 3]` will produce the list
`[f [] 1 [2, 3], f [1] 2 [3], f [1, 2] 3 []]`.
-/
def mapWithPrefixSuffix {α β} (f : List α → α → List α → β) (l : List α) : List β 
goal: List β

full_name: List.mapWithComplement
code: /--
`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]]`.
-/
def mapWithComplement {α β} (f : α → List α → β) : List α → List β 
goal: List α → List β

full_name: List.traverse
code: /--
Map each element of a `List` to an action, evaluate these actions in order,
and collect the results.
-/
protected def traverse [Applicative F] (f : α → F β) : List α → F (List β)
  
goal: List α → F (List β)

full_name: List.Perm.cons
code: /--
`Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
of each other. This is defined by induction using pairwise swaps.
-/
inductive Perm : List α → List α → Prop
  /-- `[] ~ []` -/
  | nil : Perm [] []
  /-- `l₁ ~ l₂ → x::l₁ ~ x::l₂` -/
  | cons (x : α) {l₁ l₂ : List α} : Perm l₁ l₂ → Perm (x :: l₁) (x :: l₂)
  /-- `x::y::l ~ y::x::l` -/
  | swap (x y : α) (l : List α) : Perm (y :: x :: l) (x :: y :: l)
  /-- `Perm` is transitive. -/
  | trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
goal: l₁ ~ l₂ → x :: l₁ ~ x :: l₂

full_name: List.Perm
code: /--
`Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
of each other. This is defined by induction using pairwise swaps.
-/
inductive Perm : List α → List α → Prop
  /-- `[] ~ []` -/
  | nil : Perm [] []
  /-- `l₁ ~ l₂ → x::l₁ ~ x::l₂` -/
  | cons (x : α) {l₁ l₂ : List α} : Perm l₁ l₂ → Perm (x :: l₁) (x :: l₂)
  /-- `x::y::l ~ y::x::l` -/
  | swap (x y : α) (l : List α) : Perm (y :: x :: l) (x :: y :: l)
  /-- `Perm` is transitive. -/
  | trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
goal: List α → List α → Prop

full_name: List.Perm.trans
code: /--
`Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
of each other. This is defined by induction using pairwise swaps.
-/
inductive Perm : List α → List α → Prop
  /-- `[] ~ []` -/
  | nil : Perm [] []
  /-- `l₁ ~ l₂ → x::l₁ ~ x::l₂` -/
  | cons (x : α) {l₁ l₂ : List α} : Perm l₁ l₂ → Perm (x :: l₁) (x :: l₂)
  /-- `x::y::l ~ y::x::l` -/
  | swap (x y : α) (l : List α) : Perm (y :: x :: l) (x :: y :: l)
  /-- `Perm` is transitive. -/
  | trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
goal: l₁ ~ l₂ → l₂ ~ l₃ → l₁ ~ l₃

full_name: List.Perm.nil
code: /--
`Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
of each other. This is defined by induction using pairwise swaps.
-/
inductive Perm : List α → List α → Prop
  /-- `[] ~ []` -/
  | nil : Perm [] []
  /-- `l₁ ~ l₂ → x::l₁ ~ x::l₂` -/
  | cons (x : α) {l₁ l₂ : List α} : Perm l₁ l₂ → Perm (x :: l₁) (x :: l₂)
  /-- `x::y::l ~ y::x::l` -/
  | swap (x y : α) (l : List α) : Perm (y :: x :: l) (x :: y :: l)
  /-- `Perm` is transitive. -/
  | trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
goal: [] ~ []

full_name: List.Perm.swap
code: /--
`Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
of each other. This is defined by induction using pairwise swaps.
-/
inductive Perm : List α → List α → Prop
  /-- `[] ~ []` -/
  | nil : Perm [] []
  /-- `l₁ ~ l₂ → x::l₁ ~ x::l₂` -/
  | cons (x : α) {l₁ l₂ : List α} : Perm l₁ l₂ → Perm (x :: l₁) (x :: l₂)
  /-- `x::y::l ~ y::x::l` -/
  | swap (x y : α) (l : List α) : Perm (y :: x :: l) (x :: y :: l)
  /-- `Perm` is transitive. -/
  | trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
goal: y :: x :: l ~ x :: y :: l

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___unexpand_List_Perm_1»
code: @[inherit_doc] scoped infixl:50 " ~ " => Perm
goal: Lean.PrettyPrinter.Unexpander

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___macroRules_List_term_~__1»
code: @[inherit_doc] scoped infixl:50 " ~ " => Perm
goal: Lean.Macro

full_name: List.isPerm
code: /--
`O(|l₁| * |l₂|)`. Computes whether `l₁` is a permutation of `l₂`. See `isPerm_iff` for a
characterization in terms of `List.Perm`.
-/
def isPerm [BEq α] : List α → List α → Bool
  
goal: List α → List α → Bool

full_name: List.Subperm
code: /--
`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.
-/
def Subperm (l₁ l₂ : List α) : Prop 
goal: Prop

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___macroRules_List_term_<+~__1»
code: @[inherit_doc] scoped infixl:50 " <+~ " => Subperm
goal: Lean.Macro

full_name: List.«_aux_.lake_packages_batteries_Batteries_Data_List_Basic___unexpand_List_Subperm_1»
code: @[inherit_doc] scoped infixl:50 " <+~ " => Subperm
goal: Lean.PrettyPrinter.Unexpander

full_name: List.isSubperm
code: /--
`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`.
-/
def isSubperm [BEq α] (l₁ l₂ : List α) : Bool 
goal: Bool

full_name: List.merge
code: /--
`O(|l| + |r|)`. Merge two lists using `s` as a switch.
-/
def merge (s : α → α → Bool) (l r : List α) : List α 
goal: List α

full_name: List.merge.loop
code: /--
`O(|l| + |r|)`. Merge two lists using `s` as a switch.
-/
def merge (s : α → α → Bool) (l r : List α) : List α 
goal: List α → List α → List α → List α