Documentation

Init.Data.Option.Attach

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

“Attaches” a proof that some predicate holds for an optional value, if present, returning a subtype that expresses this fact.

This function is primarily used to implement Option.attach, which allows definitions by well-founded recursion that use iteration operators (such as Option.map) to prove that an optional value drawn from a parameter is smaller than the parameter. This allows the well-founded recursion mechanism to prove that the function terminates.

Equations
Instances For
    @[inline]
    def Option.attach {α : Type u_1} (xs : Option α) :
    Option { x : α // x xs }

    “Attaches” a proof that an optional value, if present, is indeed this value, returning a subtype that expresses this fact.

    This function is primarily used to allow definitions by well-founded recursion that use iteration operators (such as Option.map) to prove that an optional value drawn from a parameter is smaller than the parameter. This allows the well-founded recursion mechanism to prove that the function terminates.

    Equations
    Instances For
      @[simp]
      theorem Option.attach_none {α : Type u_1} :
      @[simp]
      theorem Option.attachWith_none {α : Type u_1} {P : αProp} {H : ∀ (x : α), x noneP x} :
      @[simp]
      theorem Option.attach_some {α : Type u_1} {x : α} :
      (some x).attach = some x,
      @[simp]
      theorem Option.attachWith_some {α : Type u_1} {x : α} {P : αProp} (h : ∀ (b : α), b some xP b) :
      (some x).attachWith P h = some x,
      theorem Option.attach_congr {α : Type u_1} {o₁ o₂ : Option α} (h : o₁ = o₂) :
      o₁.attach = Option.map (fun (x : { x : α // x o₂ }) => x.val, ) o₂.attach
      theorem Option.attachWith_congr {α : Type u_1} {o₁ o₂ : Option α} (w : o₁ = o₂) {P : αProp} {H : ∀ (x : α), x o₁P x} :
      o₁.attachWith P H = o₂.attachWith P
      theorem Option.attach_map_val {α : Type u_1} {β : Type u_2} (o : Option α) (f : αβ) :
      Option.map (fun (i : { i : α // i o }) => f i.val) o.attach = Option.map f o
      @[reducible, inline, deprecated Option.attach_map_val (since := "2025-02-17")]
      abbrev Option.attach_map_coe {α : Type u_1} {β : Type u_2} (o : Option α) (f : αβ) :
      Option.map (fun (i : { i : α // i o }) => f i.val) o.attach = Option.map f o
      Equations
      Instances For
        theorem Option.attachWith_map_val {α : Type u_1} {β : Type u_2} {p : αProp} (f : αβ) (o : Option α) (H : ∀ (a : α), a op a) :
        Option.map (fun (i : { i : α // p i }) => f i.val) (o.attachWith p H) = Option.map f o
        @[reducible, inline, deprecated Option.attachWith_map_val (since := "2025-02-17")]
        abbrev Option.attachWith_map_coe {α : Type u_1} {β : Type u_2} {p : αProp} (f : αβ) (o : Option α) (H : ∀ (a : α), a op a) :
        Option.map (fun (i : { i : α // p i }) => f i.val) (o.attachWith p H) = Option.map f o
        Equations
        Instances For
          theorem Option.attachWith_map_subtype_val {α : Type u_1} {p : αProp} (o : Option α) (H : ∀ (a : α), a op a) :
          theorem Option.mem_attach {α : Type u_1} (o : Option α) (x : { x : α // x o }) :
          @[simp]
          theorem Option.isNone_attach {α : Type u_1} (o : Option α) :
          @[simp]
          theorem Option.isNone_attachWith {α : Type u_1} {p : αProp} (o : Option α) (H : ∀ (a : α), a op a) :
          @[simp]
          theorem Option.isSome_attach {α : Type u_1} (o : Option α) :
          @[simp]
          theorem Option.isSome_attachWith {α : Type u_1} {p : αProp} (o : Option α) (H : ∀ (a : α), a op a) :
          @[simp]
          theorem Option.attach_eq_none_iff {α : Type u_1} {o : Option α} :
          @[simp]
          theorem Option.attach_eq_some_iff {α : Type u_1} {o : Option α} {x : { x : α // x o }} :
          @[simp]
          theorem Option.attachWith_eq_none_iff {α : Type u_1} {p : αProp} {o : Option α} (H : ∀ (a : α), a op a) :
          @[simp]
          theorem Option.attachWith_eq_some_iff {α : Type u_1} {p : αProp} {o : Option α} (H : ∀ (a : α), a op a) {x : { x : α // p x }} :
          o.attachWith p H = some x o = some x.val
          @[simp]
          theorem Option.get_attach {α : Type u_1} {o : Option α} (h : o.attach.isSome = true) :
          o.attach.get h = o.get ,
          @[simp]
          theorem Option.get_attachWith {α : Type u_1} {p : αProp} {o : Option α} (H : ∀ (a : α), a op a) (h : (o.attachWith p H).isSome = true) :
          (o.attachWith p H).get h = o.get ,
          theorem Option.toList_attach {α : Type u_1} (o : Option α) :
          o.attach.toList = List.map (fun (x : { x : α // x o.toList }) => match x with | x, h => x, ) o.toList.attach
          @[simp]
          theorem Option.attach_toList {α : Type u_1} (o : Option α) :
          o.toList.attach = (Option.map (fun (x : { x : α // x o }) => match x with | a, h => a, ) o.attach).toList
          theorem Option.attach_map {α : Type u_1} {β : Type u_2} {o : Option α} (f : αβ) :
          (Option.map f o).attach = Option.map (fun (x : { x : α // x o }) => match x with | x, h => f x, ) o.attach
          theorem Option.attachWith_map {α : Type u_1} {β : Type u_2} {o : Option α} (f : αβ) {P : βProp} {H : ∀ (b : β), b Option.map f oP b} :
          (Option.map f o).attachWith P H = Option.map (fun (x : { x : α // (P f) x }) => match x with | x, h => f x, h) (o.attachWith (P f) )
          theorem Option.map_attach_eq_pmap {α : Type u_1} {β : Type u_2} {o : Option α} (f : { x : α // x o }β) :
          Option.map f o.attach = pmap (fun (a : α) (h : a o) => f a, h) o
          @[reducible, inline, deprecated Option.map_attach_eq_pmap (since := "2025-02-09")]
          abbrev Option.map_attach {α : Type u_1} {β : Type u_2} {o : Option α} (f : { x : α // x o }β) :
          Option.map f o.attach = pmap (fun (a : α) (h : a o) => f a, h) o
          Equations
          Instances For
            @[simp]
            theorem Option.map_attachWith {α : Type u_1} {β : Type u_2} {l : Option α} {P : αProp} {H : ∀ (a : α), a lP a} (f : { x : α // P x }β) :
            Option.map f (l.attachWith P H) = Option.map (fun (x : { x : α // x l }) => match x with | x, h => f x, ) l.attach
            theorem Option.map_attachWith_eq_pmap {α : Type u_1} {β : Type u_2} {o : Option α} {P : αProp} {H : ∀ (a : α), a oP a} (f : { x : α // P x }β) :
            Option.map f (o.attachWith P H) = pmap (fun (a : α) (h : a o P a) => f a, ) o
            @[simp]
            theorem Option.map_attach_eq_attachWith {α : Type u_1} {o : Option α} {p : αProp} (f : ∀ (a : α), a op a) :
            Option.map (fun (x : { x : α // x o }) => x.val, ) o.attach = o.attachWith p f
            theorem Option.attach_bind {α : Type u_1} {β : Type u_2} {o : Option α} {f : αOption β} :
            (o.bind f).attach = o.attach.bind fun (x : { x : α // x o }) => match x with | x, h => Option.map (fun (x_1 : { x_1 : β // x_1 f x }) => match x_1 with | y, h' => y, ) (f x).attach
            theorem Option.bind_attach {α : Type u_1} {β : Type u_2} {o : Option α} {f : { x : α // x o }Option β} :
            o.attach.bind f = o.pbind fun (a : α) (h : a o) => f a, h
            theorem Option.pbind_eq_bind_attach {α : Type u_1} {β : Type u_2} {o : Option α} {f : (a : α) → a oOption β} :
            o.pbind f = o.attach.bind fun (x : { x : α // x o }) => match x with | x, h => f x h
            theorem Option.attach_filter {α : Type u_1} {o : Option α} {p : αBool} :
            (Option.filter p o).attach = o.attach.bind fun (x : { x : α // x o }) => match x with | x, h => if h' : p x = true then some x, else none
            theorem Option.filter_attach {α : Type u_1} {o : Option α} {p : { x : α // x o }Bool} :
            Option.filter p o.attach = o.pbind fun (a : α) (h : a o) => if p a, h = true then some a, h else none

            unattach #

            Option.unattach is the (one-sided) inverse of Option.attach. It is a synonym for Option.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 : Option { 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 Option.unattach {α : Type u_1} {p : αProp} (o : Option { x : α // p x }) :

            Remove an attached proof that the value in an Option is indeed that value.

            This function is usually inserted automatically by Lean, rather than explicitly in code. It is introduced as an intermediate step during the elaboration of definitions by well-founded recursion.

            If this function is encountered in a proof state, the right approach is usually the tactic simp [Option.unattach, -Option.map_subtype].

            It is a synonym for Option.map Subtype.val.

            Equations
            Instances For
              @[simp]
              theorem Option.unattach_none {α : Type u_1} {p : αProp} :
              @[simp]
              theorem Option.unattach_some {α : Type u_1} {p : αProp} {a : { x : α // p x }} :
              @[simp]
              theorem Option.isSome_unattach {α : Type u_1} {p : αProp} {o : Option { x : α // p x }} :
              @[simp]
              theorem Option.isNone_unattach {α : Type u_1} {p : αProp} {o : Option { x : α // p x }} :
              @[simp]
              theorem Option.unattach_attach {α : Type u_1} (o : Option α) :
              @[simp]
              theorem Option.unattach_attachWith {α : Type u_1} {p : αProp} {o : Option α} {H : ∀ (a : α), a op a} :

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

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

              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 Option.bind_subtype {α : Type u_1} {β : Type u_2} {p : αProp} {o : Option { x : α // p x }} {f : { x : α // p x }Option β} {g : αOption β} (hf : ∀ (x : α) (h : p x), f x, h = g x) :
              @[simp]
              theorem Option.unattach_filter {α : Type u_1} {p : αProp} {o : Option { x : α // p x }} {f : { x : α // p x }Bool} {g : αBool} (hf : ∀ (x : α) (h : p x), f x, h = g x) :