Documentation

Init.Data.List.Attach

def List.pmap {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (l : List α) (H : ∀ (a : α), a lP a) :
List β

O(n). Partial map. If f : Π a, P a → β is a partial function defined on a : α satisfying P, then pmap f l h is essentially the same as map f l but is defined only when all members of l satisfy P, using the proof to apply f.

Equations
@[implemented_by _private.Init.Data.List.Attach.0.List.attachWithImpl]
def List.attachWith {α : Type u_1} (l : List α) (P : αProp) (H : ∀ (x : α), x lP x) :
List { x : α // P x }

O(1). "Attach" a proof P x that holds for all the elements of l to produce a new list with the same elements but in the type {x // P x}.

Equations
@[inline]
def List.attach {α : Type u_1} (l : List α) :
List { x : α // x l }

O(1). "Attach" the proof that the elements of l are in l to produce a new list with the same elements but in the type {x // x ∈ l}.

Equations
@[simp]
theorem List.attach_nil {α : Type u_1} :
[].attach = []
@[simp]
theorem List.attachWith_nil {α : Type u_1} {P : αProp} {H : ∀ (x : α), x []P x} :
[].attachWith P H = []
@[simp]
theorem List.pmap_eq_map {α : Type u_1} {β : Type u_2} (p : αProp) (f : αβ) (l : List α) (H : ∀ (a : α), a lp a) :
List.pmap (fun (a : α) (x : p a) => f a) l H = List.map f l
theorem List.pmap_congr_left {α : Type u_1} {β : Type u_2} {p : αProp} {q : αProp} {f : (a : α) → p aβ} {g : (a : α) → q aβ} (l : List α) {H₁ : ∀ (a : α), a lp a} {H₂ : ∀ (a : α), a lq a} (h : ∀ (a : α), a l∀ (h₁ : p a) (h₂ : q a), f a h₁ = g a h₂) :
List.pmap f l H₁ = List.pmap g l H₂
@[reducible, inline, deprecated List.pmap_congr_left]
abbrev List.pmap_congr {α : Type u_1} {β : Type u_2} {p : αProp} {q : αProp} {f : (a : α) → p aβ} {g : (a : α) → q aβ} (l : List α) {H₁ : ∀ (a : α), a lp a} {H₂ : ∀ (a : α), a lq a} (h : ∀ (a : α), a l∀ (h₁ : p a) (h₂ : q a), f a h₁ = g a h₂) :
List.pmap f l H₁ = List.pmap g l H₂
Equations
theorem List.map_pmap {α : Type u_1} {β : Type u_2} {γ : Type u_3} {p : αProp} (g : βγ) (f : (a : α) → p aβ) (l : List α) (H : ∀ (a : α), a lp a) :
List.map g (List.pmap f l H) = List.pmap (fun (a : α) (h : p a) => g (f a h)) l H
theorem List.pmap_map {β : Type u_1} {γ : Type u_2} {α : Type u_3} {p : βProp} (g : (b : β) → p bγ) (f : αβ) (l : List α) (H : ∀ (a : β), a List.map f lp a) :
List.pmap g (List.map f l) H = List.pmap (fun (a : α) (h : p (f a)) => g (f a) h) l
theorem List.attach_congr {α : Type u_1} {l₁ : List α} {l₂ : List α} (h : l₁ = l₂) :
l₁.attach = List.map (fun (x : { x : α // x l₂ }) => x.val, ) l₂.attach
theorem List.attachWith_congr {α : Type u_1} {l₁ : List α} {l₂ : List α} (w : l₁ = l₂) {P : αProp} {H : ∀ (x : α), x l₁P x} :
l₁.attachWith P H = l₂.attachWith P
@[simp]
theorem List.attach_cons {α : Type u_1} {x : α} {xs : List α} :
(x :: xs).attach = x, :: List.map (fun (x_1 : { x : α // x xs }) => match x_1 with | y, h => y, ) xs.attach
@[simp]
theorem List.attachWith_cons {α : Type u_1} {x : α} {xs : List α} {p : αProp} (h : ∀ (a : α), a x :: xsp a) :
(x :: xs).attachWith p h = x, :: xs.attachWith p
theorem List.pmap_eq_map_attach {α : Type u_1} {β : Type u_2} {p : αProp} (f : (a : α) → p aβ) (l : List α) (H : ∀ (a : α), a lp a) :
List.pmap f l H = List.map (fun (x : { x : α // x l }) => f x.val ) l.attach
theorem List.attach_map_coe {α : Type u_1} {β : Type u_2} (l : List α) (f : αβ) :
List.map (fun (i : { i : α // i l }) => f i.val) l.attach = List.map f l
theorem List.attach_map_val {α : Type u_1} {β : Type u_2} (l : List α) (f : αβ) :
List.map (fun (i : { x : α // x l }) => f i.val) l.attach = List.map f l
@[simp]
theorem List.attach_map_subtype_val {α : Type u_1} (l : List α) :
List.map Subtype.val l.attach = l
theorem List.attachWith_map_coe {α : Type u_1} {β : Type u_2} {p : αProp} (f : αβ) (l : List α) (H : ∀ (a : α), a lp a) :
List.map (fun (i : { i : α // p i }) => f i.val) (l.attachWith p H) = List.map f l
theorem List.attachWith_map_val {α : Type u_1} {β : Type u_2} {p : αProp} (f : αβ) (l : List α) (H : ∀ (a : α), a lp a) :
List.map (fun (i : { x : α // p x }) => f i.val) (l.attachWith p H) = List.map f l
@[simp]
theorem List.attachWith_map_subtype_val {α : Type u_1} {p : αProp} (l : List α) (H : ∀ (a : α), a lp a) :
List.map Subtype.val (l.attachWith p H) = l
@[simp]
theorem List.mem_attach {α : Type u_1} (l : List α) (x : { x : α // x l }) :
x l.attach
@[simp]
theorem List.mem_pmap {α : Type u_1} {β : Type u_2} {p : αProp} {f : (a : α) → p aβ} {l : List α} {H : ∀ (a : α), a lp a} {b : β} :
b List.pmap f l H ∃ (a : α), ∃ (h : a l), f a = b
theorem List.mem_pmap_of_mem {α : Type u_1} {β : Type u_2} {p : αProp} {f : (a : α) → p aβ} {l : List α} {H : ∀ (a : α), a lp a} {a : α} (h : a l) :
f a List.pmap f l H
@[simp]
theorem List.length_pmap {α : Type u_1} {β : Type u_2} {p : αProp} {f : (a : α) → p aβ} {l : List α} {H : ∀ (a : α), a lp a} :
(List.pmap f l H).length = l.length
@[simp]
theorem List.length_attach {α : Type u_1} {L : List α} :
L.attach.length = L.length
@[simp]
theorem List.length_attachWith {α : Type u_1} {p : αProp} {l : List α} {H : ∀ (x : α), x lp x} :
(l.attachWith p H).length = l.length
@[simp]
theorem List.pmap_eq_nil_iff {α : Type u_1} {β : Type u_2} {p : αProp} {f : (a : α) → p aβ} {l : List α} {H : ∀ (a : α), a lp a} :
List.pmap f l H = [] l = []
theorem List.pmap_ne_nil_iff {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) {xs : List α} (H : ∀ (a : α), a xsP a) :
List.pmap f xs H [] xs []
@[simp]
theorem List.attach_eq_nil_iff {α : Type u_1} {l : List α} :
l.attach = [] l = []
theorem List.attach_ne_nil_iff {α : Type u_1} {l : List α} :
l.attach [] l []
@[simp]
theorem List.attachWith_eq_nil_iff {α : Type u_1} {l : List α} {P : αProp} {H : ∀ (a : α), a lP a} :
l.attachWith P H = [] l = []
theorem List.attachWith_ne_nil_iff {α : Type u_1} {l : List α} {P : αProp} {H : ∀ (a : α), a lP a} :
l.attachWith P H [] l []
@[reducible, inline, deprecated List.pmap_eq_nil_iff]
abbrev List.pmap_eq_nil {α : Type u_1} {β : Type u_2} {p : αProp} {f : (a : α) → p aβ} {l : List α} {H : ∀ (a : α), a lp a} :
List.pmap f l H = [] l = []
Equations
@[reducible, inline, deprecated List.pmap_ne_nil_iff]
abbrev List.pmap_ne_nil {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) {xs : List α} (H : ∀ (a : α), a xsP a) :
List.pmap f xs H [] xs []
Equations
@[reducible, inline, deprecated List.attach_eq_nil_iff]
abbrev List.attach_eq_nil {α : Type u_1} {l : List α} :
l.attach = [] l = []
Equations
@[reducible, inline, deprecated List.attach_ne_nil_iff]
abbrev List.attach_ne_nil {α : Type u_1} {l : List α} :
l.attach [] l []
Equations
@[simp]
theorem List.getElem?_pmap {α : Type u_1} {β : Type u_2} {p : αProp} (f : (a : α) → p aβ) {l : List α} (h : ∀ (a : α), a lp a) (n : Nat) :
(List.pmap f l h)[n]? = Option.pmap f l[n]?
theorem List.get?_pmap {α : Type u_1} {β : Type u_2} {p : αProp} (f : (a : α) → p aβ) {l : List α} (h : ∀ (a : α), a lp a) (n : Nat) :
(List.pmap f l h).get? n = Option.pmap f (l.get? n)
@[simp]
theorem List.getElem_pmap {α : Type u_1} {β : Type u_2} {p : αProp} (f : (a : α) → p aβ) {l : List α} (h : ∀ (a : α), a lp a) {n : Nat} (hn : n < (List.pmap f l h).length) :
(List.pmap f l h)[n] = f l[n]
theorem List.get_pmap {α : Type u_1} {β : Type u_2} {p : αProp} (f : (a : α) → p aβ) {l : List α} (h : ∀ (a : α), a lp a) {n : Nat} (hn : n < (List.pmap f l h).length) :
(List.pmap f l h).get n, hn = f (l.get n, )
@[simp]
theorem List.getElem?_attachWith {α : Type u_1} {xs : List α} {i : Nat} {P : αProp} {H : ∀ (a : α), a xsP a} :
(xs.attachWith P H)[i]? = Option.pmap Subtype.mk xs[i]?
@[simp]
theorem List.getElem?_attach {α : Type u_1} {xs : List α} {i : Nat} :
xs.attach[i]? = Option.pmap Subtype.mk xs[i]?
@[simp]
theorem List.getElem_attachWith {α : Type u_1} {xs : List α} {P : αProp} {H : ∀ (a : α), a xsP a} {i : Nat} (h : i < (xs.attachWith P H).length) :
(xs.attachWith P H)[i] = xs[i],
@[simp]
theorem List.getElem_attach {α : Type u_1} {xs : List α} {i : Nat} (h : i < xs.attach.length) :
xs.attach[i] = xs[i],
@[simp]
theorem List.head?_pmap {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (xs : List α) (H : ∀ (a : α), a xsP a) :
(List.pmap f xs H).head? = Option.map (fun (x : { x : α // x xs }) => match x with | a, m => f a ) xs.attach.head?
@[simp]
theorem List.head_pmap {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (xs : List α) (H : ∀ (a : α), a xsP a) (h : List.pmap f xs H []) :
(List.pmap f xs H).head h = f (xs.head )
@[simp]
theorem List.head?_attachWith {α : Type u_1} {P : αProp} {xs : List α} (H : ∀ (a : α), a xsP a) :
(xs.attachWith P H).head? = xs.head?.pbind fun (a : α) (h : a xs.head?) => some a,
@[simp]
theorem List.head_attachWith {α : Type u_1} {P : αProp} {xs : List α} {H : ∀ (a : α), a xsP a} (h : xs.attachWith P H []) :
(xs.attachWith P H).head h = xs.head ,
@[simp]
theorem List.head?_attach {α : Type u_1} (xs : List α) :
xs.attach.head? = xs.head?.pbind fun (a : α) (h : a xs.head?) => some a,
@[simp]
theorem List.head_attach {α : Type u_1} {xs : List α} (h : xs.attach []) :
xs.attach.head h = xs.head ,
@[simp]
theorem List.tail_pmap {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (xs : List α) (H : ∀ (a : α), a xsP a) :
(List.pmap f xs H).tail = List.pmap f xs.tail
@[simp]
theorem List.tail_attachWith {α : Type u_1} {P : αProp} {xs : List α} {H : ∀ (a : α), a xsP a} :
(xs.attachWith P H).tail = xs.tail.attachWith P
@[simp]
theorem List.tail_attach {α : Type u_1} (xs : List α) :
xs.attach.tail = List.map (fun (x : { x : α // x xs.tail }) => match x with | x, h => x, ) xs.tail.attach
theorem List.foldl_pmap {α : Type u_1} {β : Type u_2} {γ : Type u_3} (l : List α) {P : αProp} (f : (a : α) → P aβ) (H : ∀ (a : α), a lP a) (g : γβγ) (x : γ) :
List.foldl g x (List.pmap f l H) = List.foldl (fun (acc : γ) (a : { x : α // x l }) => g acc (f a.val )) x l.attach
theorem List.foldr_pmap {α : Type u_1} {β : Type u_2} {γ : Type u_3} (l : List α) {P : αProp} (f : (a : α) → P aβ) (H : ∀ (a : α), a lP a) (g : βγγ) (x : γ) :
List.foldr g x (List.pmap f l H) = List.foldr (fun (a : { x : α // x l }) (acc : γ) => g (f a.val ) acc) x l.attach
theorem List.foldl_attach {α : Type u_1} {β : Type u_2} (l : List α) (f : βαβ) (b : β) :
List.foldl (fun (acc : β) (t : { x : α // x l }) => f acc t.val) b l.attach = List.foldl f b l

If we fold over l.attach with a function that ignores the membership predicate, we get the same results as folding over l directly.

This is useful when we need to use attach to show termination.

Unfortunately this can't be applied by simp because of the higher order unification problem, and even when rewriting we need to specify the function explicitly.

theorem List.foldr_attach {α : Type u_1} {β : Type u_2} (l : List α) (f : αββ) (b : β) :
List.foldr (fun (t : { x : α // x l }) (acc : β) => f t.val acc) b l.attach = List.foldr f b l

If we fold over l.attach with a function that ignores the membership predicate, we get the same results as folding over l directly.

This is useful when we need to use attach to show termination.

Unfortunately this can't be applied by simp because of the higher order unification problem, and even when rewriting we need to specify the function explicitly.

theorem List.attach_map {α : Type u_1} {β : Type u_2} {l : List α} (f : αβ) :
(List.map f l).attach = List.map (fun (x : { x : α // x l }) => match x with | x, h => f x, ) l.attach
theorem List.attachWith_map {α : Type u_1} {β : Type u_2} {l : List α} (f : αβ) {P : βProp} {H : ∀ (b : β), b List.map f lP b} :
(List.map f l).attachWith P H = List.map (fun (x : { x : α // (P f) x }) => match x with | x, h => f x, h) (l.attachWith (P f) )
theorem List.map_attachWith {α : Type u_1} {β : Type u_2} {l : List α} {P : αProp} {H : ∀ (a : α), a lP a} (f : { x : α // P x }β) :
List.map f (l.attachWith P H) = List.pmap (fun (a : α) (h : a l P a) => f a, ) l
theorem List.map_attach {α : Type u_1} {β : Type u_2} {l : List α} (f : { x : α // x l }β) :
List.map f l.attach = List.pmap (fun (a : α) (h : a l) => f a, h) l

See also pmap_eq_map_attach for writing pmap in terms of map and attach.

theorem List.attach_filterMap {α : Type u_1} {β : Type u_2} {l : List α} {f : αOption β} :
(List.filterMap f l).attach = List.filterMap (fun (x : { x : α // x l }) => match x with | x, h => (f x).pbind fun (b : β) (m : b f x) => some b, ) l.attach
theorem List.attach_filter {α : Type u_1} {l : List α} (p : αBool) :
(List.filter p l).attach = List.filterMap (fun (x : { x : α // x l }) => if w : p x.val = true then some x.val, else none) l.attach
theorem List.pmap_pmap {α : Type u_1} {β : Type u_2} {γ : Type u_3} {p : αProp} {q : βProp} (g : (a : α) → p aβ) (f : (b : β) → q bγ) (l : List α) (H₁ : ∀ (a : α), a lp a) (H₂ : ∀ (a : β), a List.pmap g l H₁q a) :
List.pmap f (List.pmap g l H₁) H₂ = List.pmap (fun (a : { x : α // x l }) (h : p a.val) => f (g a.val h) ) l.attach
@[simp]
theorem List.pmap_append {ι : Type u_1} {α : Type u_2} {p : ιProp} (f : (a : ι) → p aα) (l₁ : List ι) (l₂ : List ι) (h : ∀ (a : ι), a l₁ ++ l₂p a) :
List.pmap f (l₁ ++ l₂) h = List.pmap f l₁ ++ List.pmap f l₂
theorem List.pmap_append' {α : Type u_1} {β : Type u_2} {p : αProp} (f : (a : α) → p aβ) (l₁ : List α) (l₂ : List α) (h₁ : ∀ (a : α), a l₁p a) (h₂ : ∀ (a : α), a l₂p a) :
List.pmap f (l₁ ++ l₂) = List.pmap f l₁ h₁ ++ List.pmap f l₂ h₂
@[simp]
theorem List.attach_append {α : Type u_1} (xs : List α) (ys : List α) :
(xs ++ ys).attach = List.map (fun (x : { x : α // x xs }) => match x with | x, h => x, ) xs.attach ++ List.map (fun (x : { x : α // x ys }) => match x with | x, h => x, ) ys.attach
@[simp]
theorem List.attachWith_append {α : Type u_1} {P : αProp} {xs : List α} {ys : List α} {H : ∀ (a : α), a xs ++ ysP a} :
(xs ++ ys).attachWith P H = xs.attachWith P ++ ys.attachWith P
@[simp]
theorem List.pmap_reverse {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (xs : List α) (H : ∀ (a : α), a xs.reverseP a) :
List.pmap f xs.reverse H = (List.pmap f xs ).reverse
theorem List.reverse_pmap {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (xs : List α) (H : ∀ (a : α), a xsP a) :
(List.pmap f xs H).reverse = List.pmap f xs.reverse
@[simp]
theorem List.attachWith_reverse {α : Type u_1} {P : αProp} {xs : List α} {H : ∀ (a : α), a xs.reverseP a} :
xs.reverse.attachWith P H = (xs.attachWith P ).reverse
theorem List.reverse_attachWith {α : Type u_1} {P : αProp} {xs : List α} {H : ∀ (a : α), a xsP a} :
(xs.attachWith P H).reverse = xs.reverse.attachWith P
@[simp]
theorem List.attach_reverse {α : Type u_1} (xs : List α) :
xs.reverse.attach = List.map (fun (x : { x : α // x xs }) => match x with | x, h => x, ) xs.attach.reverse
theorem List.reverse_attach {α : Type u_1} (xs : List α) :
xs.attach.reverse = List.map (fun (x : { x : α // x xs.reverse }) => match x with | x, h => x, ) xs.reverse.attach
@[simp]
theorem List.getLast?_pmap {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (xs : List α) (H : ∀ (a : α), a xsP a) :
(List.pmap f xs H).getLast? = Option.map (fun (x : { x : α // x xs }) => match x with | a, m => f a ) xs.attach.getLast?
@[simp]
theorem List.getLast_pmap {α : Type u_1} {β : Type u_2} {P : αProp} (f : (a : α) → P aβ) (xs : List α) (H : ∀ (a : α), a xsP a) (h : List.pmap f xs H []) :
(List.pmap f xs H).getLast h = f (xs.getLast )
@[simp]
theorem List.getLast?_attachWith {α : Type u_1} {P : αProp} {xs : List α} {H : ∀ (a : α), a xsP a} :
(xs.attachWith P H).getLast? = xs.getLast?.pbind fun (a : α) (h : a xs.getLast?) => some a,
@[simp]
theorem List.getLast_attachWith {α : Type u_1} {P : αProp} {xs : List α} {H : ∀ (a : α), a xsP a} (h : xs.attachWith P H []) :
(xs.attachWith P H).getLast h = xs.getLast ,
@[simp]
theorem List.getLast?_attach {α : Type u_1} {xs : List α} :
xs.attach.getLast? = xs.getLast?.pbind fun (a : α) (h : a xs.getLast?) => some a,
@[simp]
theorem List.getLast_attach {α : Type u_1} {xs : List α} (h : xs.attach []) :
xs.attach.getLast h = xs.getLast ,
@[simp]
theorem List.countP_attach {α : Type u_1} (l : List α) (p : αBool) :
List.countP (fun (a : { x : α // x l }) => p a.val) l.attach = List.countP p l
@[simp]
theorem List.countP_attachWith {α : Type u_1} {p : αProp} (l : List α) (H : ∀ (a : α), a lp a) (q : αBool) :
List.countP (fun (a : { x : α // p x }) => q a.val) (l.attachWith p H) = List.countP q l
@[simp]
theorem List.count_attach {α : Type u_1} [DecidableEq α] (l : List α) (a : { x : α // x l }) :
List.count a l.attach = List.count a.val l
@[simp]
theorem List.count_attachWith {α : Type u_1} [DecidableEq α] {p : αProp} (l : List α) (H : ∀ (a : α), a lp a) (a : { x : α // p x }) :
List.count a (l.attachWith p H) = List.count a.val l

unattach #

List.unattach is the (one-sided) inverse of List.attach. It is a synonym for List.map Subtype.val.

We use it by providing a simp lemma l.attach.unattach = l, and simp lemmas which recognize higher order functions applied to l : List { x // p x } which only depend on the value, not the predicate, and rewrite these in terms of a simpler function applied to l.unattach.

Further, we provide simp lemmas that push unattach inwards.

def List.unattach {α : Type u_1} {p : αProp} (l : List { x : α // p x }) :
List α

A synonym for l.map (·.val). Mostly this should not be needed by users. It is introduced as an intermediate step by lemmas such as map_subtype, and is ideally subsequently simplified away by unattach_attach.

If not, usually the right approach is simp [List.unattach, -List.map_subtype] to unfold.

Equations
  • l.unattach = List.map (fun (x : { x : α // p x }) => x.val) l
@[simp]
theorem List.unattach_nil {α : Type u_1} {p : αProp} :
[].unattach = []
@[simp]
theorem List.unattach_cons {α : Type u_1} {p : αProp} {a : { x : α // p x }} {l : List { x : α // p x }} :
(a :: l).unattach = a.val :: l.unattach
@[simp]
theorem List.length_unattach {α : Type u_1} {p : αProp} {l : List { x : α // p x }} :
l.unattach.length = l.length
@[simp]
theorem List.unattach_attach {α : Type u_1} {l : List α} :
l.attach.unattach = l
@[simp]
theorem List.unattach_attachWith {α : Type u_1} {p : αProp} {l : List α} {H : ∀ (a : α), a lp a} :
(l.attachWith p H).unattach = l

Recognizing higher order functions on subtypes using a function that only depends on the value. #

@[simp]
theorem List.foldl_subtype {α : Type u_1} {β : Type u_2} {p : αProp} {l : List { x : α // p x }} {f : β{ x : α // p x }β} {g : βαβ} {x : β} {hf : ∀ (b : β) (x : α) (h : p x), f b x, h = g b x} :
List.foldl f x l = List.foldl g x l.unattach

This lemma identifies folds over lists of subtypes, where the function only depends on the value, not the proposition, and simplifies these to the function directly taking the value.

@[simp]
theorem List.foldr_subtype {α : Type u_1} {β : Type u_2} {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }ββ} {g : αββ} {x : β} {hf : ∀ (x : α) (h : p x) (b : β), f x, h b = g x b} :
List.foldr f x l = List.foldr g x l.unattach

This lemma identifies folds over lists of subtypes, where the function only depends on the value, not the proposition, and simplifies these to the function directly taking the value.

@[simp]
theorem List.map_subtype {α : Type u_1} {β : Type u_2} {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }β} {g : αβ} {hf : ∀ (x : α) (h : p x), f x, h = g x} :
List.map f l = List.map g l.unattach

This lemma identifies maps over lists of subtypes, where the function only depends on the value, not the proposition, and simplifies these to the function directly taking the value.

@[simp]
theorem List.filterMap_subtype {α : Type u_1} {β : Type u_2} {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }Option β} {g : αOption β} {hf : ∀ (x : α) (h : p x), f x, h = g x} :
@[simp]
theorem List.bind_subtype {α : Type u_1} {β : Type u_2} {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }List β} {g : αList β} {hf : ∀ (x : α) (h : p x), f x, h = g x} :
l.bind f = l.unattach.bind g
@[simp]
theorem List.unattach_filter {α : Type u_1} {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }Bool} {g : αBool} {hf : ∀ (x : α) (h : p x), f x, h = g x} :
(List.filter f l).unattach = List.filter g l.unattach

Simp lemmas pushing unattach inwards. #

@[simp]
theorem List.unattach_reverse {α : Type u_1} {p : αProp} {l : List { x : α // p x }} :
l.reverse.unattach = l.unattach.reverse
@[simp]
theorem List.unattach_append {α : Type u_1} {p : αProp} {l₁ : List { x : α // p x }} {l₂ : List { x : α // p x }} :
(l₁ ++ l₂).unattach = l₁.unattach ++ l₂.unattach
@[simp]
theorem List.unattach_join {α : Type u_1} {p : αProp} {l : List (List { x : α // p x })} :
l.join.unattach = (List.map List.unattach l).join
@[simp]
theorem List.unattach_replicate {α : Type u_1} {p : αProp} {n : Nat} {x : { x : α // p x }} :
(List.replicate n x).unattach = List.replicate n x.val