/- Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro Coinductive formalization of unbounded computations. ! This file was ported from Lean 3 source module data.seq.computation ! leanprover-community/mathlib commit 1f0096e6caa61e9c849ec2adbd227e960e9dff58 ! Please do not edit these lines, except to modify the commit id ! if you have ported upstream changes. -/ import Mathlib.Data.Stream.Init import Mathlib.Tactic.Common /-! # Coinductive formalization of unbounded computations. This file provides a `Computation` type where `Computation α` is the type of unbounded computations returning `α`. -/ open Function universe u v w /- coinductive Computation (α : Type u) : Type u | pure : α → Computation α | think : Computation α → Xomputation α -/ /-- `Computation α` is the type of unbounded computations returning `α`. An element of `Computation α` is an infinite sequence of `Option α` such that if `f n = some a` for some `n` then it is constantly `some a` after that. -/ def Computation (α :α: Type uType u) :Type u: Type (u+1)Type u := { f : Stream' (OptionType u: Type (u+1)α) // ∀ ⦃α: Type unn: ?m.13a⦄, fa: ?m.16n = somen: ?m.13a → f (a: ?m.16n +n: ?m.131) = some1: ?m.58a } #align computation Computation namespace Computation variable {a: ?m.16α :α: Type uType u} {Type u: Type (u+1)β :β: Type vType v} {Type v: Type (v+1)γ :γ: Type wType w} -- constructors /-- `pure a` is the computation that immediately terminates with result `a`. -/ -- porting notes: `return` is reserved, so changed to `pure` defType w: Type (w+1)pure (pure: α → Computation αa :a: αα) : Computationα: Type uα := ⟨Stream'.const (someα: Type ua), funa: α__: ?m.183_ =>_: ?m.186id⟩ #align computation.returnid: ∀ {α : Sort ?u.188}, α → αComputation.pureComputation.pure: {α : Type u} → α → Computation αinstance : CoeTCinstance: {α : Type u} → CoeTC α (Computation α)α (Computationα: Type uα) := ⟨α: Type upure⟩ /- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/ -- note [use has_coe_t] /-- `think c` is the computation that delays for one "tick" and then performs computation `c`. -/ defpure: {α : Type ?u.313} → α → Computation αthink (think: {α : Type u} → Computation α → Computation αc : Computationc: Computation αα) : Computationα: Type uα := ⟨Stream'.cons noneα: Type uc.1, func: Computation αnn: ?m.423aa: ?m.426h =>h: ?m.429Goals accomplished! 🐙Stream'.cons none (↑c) (n + 1) = some a
zeroStream'.cons none (↑c) (Nat.zero + 1) = some a
succStream'.cons none (↑c) (Nat.succ n + 1) = some aStream'.cons none (↑c) (n + 1) = some a
zeroStream'.cons none (↑c) (Nat.zero + 1) = some a
zeroStream'.cons none (↑c) (Nat.zero + 1) = some a
succStream'.cons none (↑c) (Nat.succ n + 1) = some aGoals accomplished! 🐙Stream'.cons none (↑c) (n + 1) = some a
succStream'.cons none (↑c) (Nat.succ n + 1) = some a
succStream'.cons none (↑c) (Nat.succ n + 1) = some a⟩ #align computation.thinkGoals accomplished! 🐙Computation.think /-- `thinkN c n` is the computation that delays for `n` ticks and then performs computation `c`. -/ defComputation.think: {α : Type u} → Computation α → Computation αthinkN (thinkN: {α : Type u} → Computation α → ℕ → Computation αc : Computationc: Computation αα) :α: Type uℕ → Computationℕ: Typeα |α: Type u0 =>0: ℕc |c: Computation αn + 1 =>n: ℕthink (think: {α : Type ?u.749} → Computation α → Computation αthinkNthinkN: Computation α → ℕ → Computation αcc: Computation αn) set_option linter.uppercaseLean3 false in #align computation.thinkNn: ℕComputation.thinkN -- check for immediate result /-- `head c` is the first step of computation, either `some a` if `c = pure a` or `none` if `c = think c'`. -/ defComputation.thinkN: {α : Type u} → Computation α → ℕ → Computation αhead (head: {α : Type u} → Computation α → Option αc : Computationc: Computation αα) : Optionα: Type uα :=α: Type uc.1.head #align computation.headc: Computation αComputation.head -- one step of computation /-- `tail c` is the remainder of computation, either `c` if `c = pure a` or `c'` if `c = think c'`. -/ defComputation.head: {α : Type u} → Computation α → Option αtail (tail: {α : Type u} → Computation α → Computation αc : Computationc: Computation αα) : Computationα: Type uα := ⟨α: Type uc.1.tail, func: Computation α__: ?m.1166__: ?m.1169h =>h: ?m.1172c.2c: Computation αh⟩ #align computation.tailh: ?m.1172Computation.tail /-- `empty α` is the computation that never returns, an infinite sequence of `think`s. -/ defComputation.tail: {α : Type u} → Computation α → Computation αempty (empty: (α : Type ?u.1308) → Computation αα) : Computationα: ?m.1305α := ⟨Stream'.const none, funα: ?m.1305__: ?m.1336_ =>_: ?m.1339id⟩ #align computation.emptyid: ∀ {α : Sort ?u.1341}, α → αComputation.emptyComputation.empty: (α : Type u_1) → Computation αinstance : Inhabited (Computationinstance: {α : Type u} → Inhabited (Computation α)α) := ⟨α: Type uemptyempty: (α : Type ?u.1443) → Computation α_⟩ /-- `run_for c n` evaluates `c` for `n` steps and returns the result, or `none` if it did not terminate after `n` steps. -/ def_: Type ?u.1443runFor : ComputationrunFor: Computation α → ℕ → Option αα →α: Type uℕ → Optionℕ: Typeα := Subtype.val #align computation.run_forα: Type uComputation.runFor /-- `destruct c` is the destructor for `Computation α` as a coinductive type. It returns `inl a` if `c = pure a` and `inr c'` if `c = think c'`. -/ defComputation.runFor: {α : Type u} → Computation α → ℕ → Option αdestruct (destruct: Computation α → α ⊕ Computation αc : Computationc: Computation αα) : Sumα: Type uα (Computationα: Type uα) := matchα: Type uc.1c: Computation α0 with | none => Sum.inr (0: ?m.1616tailtail: {α : Type ?u.1643} → Computation α → Computation αc) | somec: Computation αa => Sum.inla: αa #align computation.destructa: αComputation.destruct /-- `run c` is an unsound meta function that runs `c` to completion, possibly resulting in an infinite loop in the VM. -/ unsafe defComputation.destruct: {α : Type u} → Computation α → α ⊕ Computation αrun : Computationrun: {α : Type u} → Computation α → αα →α: Type uα |α: Type uc => matchc: ?m.1911destructdestruct: {α : Type ?u.1913} → Computation α → α ⊕ Computation αc with | Sum.inlc: ?m.1911a =>a: αa | Sum.inra: αca =>ca: Computation αrunrun: Computation α → αca #align computation.runca: Computation αComputation.run theorem destruct_eq_pure {Computation.run: {α : Type u} → Computation α → αs : Computations: Computation αα} {α: Type ua :a: αα} :α: Type udestructdestruct: {α : Type ?u.2162} → Computation α → α ⊕ Computation αs = Sum.inls: Computation αa →a: αs =s: Computation αpurepure: {α : Type ?u.2205} → α → Computation αa :=a: αGoals accomplished! 🐙α: Type u
β: Type v
γ: Type w
s: Computation α
a: α
x✝: Option α
f0✝: ↑s 0 = x✝
f0: ↑s 0 = none
h: (match none with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inl a
noneα: Type u
β: Type v
γ: Type w
s: Computation α
a: α
x✝: Option α
f0✝: ↑s 0 = x✝
val✝: α
f0: ↑s 0 = some val✝
h: (match some val✝ with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inl a
someGoals accomplished! 🐙α: Type u
β: Type v
γ: Type w
s: Computation α
a: α
x✝: Option α
f0✝: ↑s 0 = x✝
val✝: α
f0: ↑s 0 = some val✝
h: (match some val✝ with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inl a
some.a.h.zeroα: Type u
β: Type v
γ: Type w
s: Computation α
a: α
x✝: Option α
f0✝: ↑s 0 = x✝
val✝: α
f0: ↑s 0 = some val✝
h: (match some val✝ with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inl a
n: ℕ
IH: ↑s n = ↑(pure a) n
some.a.h.succα: Type u
β: Type v
γ: Type w
s: Computation α
a: α
x✝: Option α
f0✝: ↑s 0 = x✝
val✝: α
f0: ↑s 0 = some val✝
h: (match some val✝ with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inl a
some.a.h.zeroα: Type u
β: Type v
γ: Type w
s: Computation α
a: α
x✝: Option α
f0✝: ↑s 0 = x✝
val✝: α
f0: ↑s 0 = some val✝
h: (match some val✝ with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inl a
n: ℕ
IH: ↑s n = ↑(pure a) n
some.a.h.succGoals accomplished! 🐙#align computation.destruct_eq_ret Computation.destruct_eq_pure theorem destruct_eq_think {Goals accomplished! 🐙s : Computations: Computation αα} {α: Type us'} :s': ?m.2494destructdestruct: {α : Type ?u.2499} → Computation α → α ⊕ Computation αs = Sum.inrs: Computation αs' →s': ?m.2494s =s: Computation αthinkthink: {α : Type ?u.2542} → Computation α → Computation αs' :=s': ?m.2494Goals accomplished! 🐙
none
some
none
someα: Type u
β: Type v
γ: Type w
s, s': Computation α
x✝: Option α
f0✝: ↑s 0 = x✝
f0: ↑s 0 = none
h: (match none with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inr s'
noneα: Type u
β: Type v
γ: Type w
s, s': Computation α
x✝: Option α
f0✝: ↑s 0 = x✝
a': α
f0: ↑s 0 = some a'
h: (match some a' with | none => Sum.inr (tail s) | some a => Sum.inl a) = Sum.inr s'
someα: Type u
β: Type v
γ: Type w
s': Computation α
x✝: Option α
f: Stream' (Option α)
al: ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0✝: ↑{ val := f, property := al } 0 = x✝
f0: ↑{ val := f, property := al } 0 = none
h': tail { val := f, property := al } = s'
none.mk.af = Stream'.cons none (Stream'.tail f)α: Type u
β: Type v
γ: Type w
s': Computation α
x✝: Option α
f: Stream' (Option α)
al: ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0✝: ↑{ val := f, property := al } 0 = x✝
f0: ↑{ val := f, property := al } 0 = none
h': tail { val := f, property := al } = s'
none.mk.af = Stream'.cons none (Stream'.tail f)α: Type u
β: Type v
γ: Type w
s': Computation α
x✝: Option α
f: Stream' (Option α)
al: ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0✝: ↑{ val := f, property := al } 0 = x✝
f0: ↑{ val := f, property := al } 0 = none
h': tail { val := f, property := al } = s'
none.mk.af = Stream'.cons (↑{ val := f, property := al } 0) (Stream'.tail f)α: Type u
β: Type v
γ: Type w
s': Computation α
x✝: Option α
f: Stream' (Option α)
al: ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = some a → f (n + 1) = some a
f0✝: ↑{ val := f, property := al } 0 = x✝
f0: ↑{ val := f, property := al } 0 = none
h': tail { val := f, property := al } = s'
none.mk.af = Stream'.cons (↑{ val := f, property := al } 0) (Stream'.tail f)Goals accomplished! 🐙#align computation.destruct_eq_think Computation.destruct_eq_think @[simp] theorem destruct_pure (Goals accomplished! 🐙a :a: αα) :α: Type udestruct (destruct: {α : Type ?u.2892} → Computation α → α ⊕ Computation αpurepure: {α : Type ?u.2894} → α → Computation αa) = Sum.inla: αa := rfl #align computation.destruct_ret Computation.destruct_pure @[simp] theorem destruct_think : ∀a: αs : Computations: Computation αα,α: Type udestruct (destruct: {α : Type ?u.2974} → Computation α → α ⊕ Computation αthinkthink: {α : Type ?u.2976} → Computation α → Computation αs) = Sum.inrs: Computation αs | ⟨_, _⟩ => rfl #align computation.destruct_think Computation.destruct_think @[simp] theorem destruct_empty :s: Computation αdestruct (destruct: {α : Type ?u.3250} → Computation α → α ⊕ Computation αemptyempty: (α : Type ?u.3252) → Computation αα) = Sum.inr (α: Type uemptyempty: (α : Type ?u.3259) → Computation αα) := rfl #align computation.destruct_empty Computation.destruct_empty @[simp] theorem head_pure (α: Type ua :a: αα) :α: Type uhead (head: {α : Type ?u.3335} → Computation α → Option αpurepure: {α : Type ?u.3337} → α → Computation αa) = somea: αa := rfl #align computation.head_ret Computation.head_pure @[simp] theorema: αhead_think (head_think: ∀ (s : Computation α), head (think s) = nones : Computations: Computation αα) :α: Type uhead (head: {α : Type ?u.3374} → Computation α → Option αthinkthink: {α : Type ?u.3376} → Computation α → Computation αs) = none := rfl #align computation.head_thinks: Computation αComputation.head_think @[simp] theorem head_empty :Computation.head_think: ∀ {α : Type u} (s : Computation α), head (think s) = nonehead (head: {α : Type ?u.3446} → Computation α → Option αemptyempty: (α : Type ?u.3448) → Computation αα) = none := rfl #align computation.head_empty Computation.head_empty @[simp] theorem tail_pure (α: Type ua :a: αα) :α: Type utail (tail: {α : Type ?u.3505} → Computation α → Computation αpurepure: {α : Type ?u.3507} → α → Computation αa) =a: αpurepure: {α : Type ?u.3511} → α → Computation αa := rfl #align computation.tail_ret Computation.tail_pure @[simp] theorema: αtail_think (tail_think: ∀ {α : Type u} (s : Computation α), tail (think s) = ss : Computations: Computation αα) :α: Type utail (tail: {α : Type ?u.3550} → Computation α → Computation αthinkthink: {α : Type ?u.3552} → Computation α → Computation αs) =s: Computation αs :=s: Computation αGoals accomplished! 🐙#align computation.tail_thinkGoals accomplished! 🐙Computation.tail_think @[simp] theorem tail_empty :Computation.tail_think: ∀ {α : Type u} (s : Computation α), tail (think s) = stail (tail: {α : Type ?u.3711} → Computation α → Computation αemptyempty: (α : Type ?u.3713) → Computation αα) =α: Type uemptyempty: (α : Type ?u.3716) → Computation αα := rfl #align computation.tail_empty Computation.tail_empty theorem think_empty :α: Type uemptyempty: (α : Type ?u.3746) → Computation αα =α: Type uthink (think: {α : Type ?u.3747} → Computation α → Computation αemptyempty: (α : Type ?u.3749) → Computation αα) := destruct_eq_think destruct_empty #align computation.think_empty Computation.think_empty /-- Recursion principle for computations, compare with `List.recOn`. -/ defα: Type urecOn {recOn: {α : Type u} → {C : Computation α → Sort v} → (s : Computation α) → ((a : α) → C (pure a)) → ((s : Computation α) → C (think s)) → C sC : ComputationC: Computation α → Sort vα →α: Type uSortSort v: Type vv} (Sort v: Type vs : Computations: Computation αα) (α: Type uh1 : ∀h1: (a : α) → C (pure a)a,a: ?m.3791C (C: Computation α → Sort vpurepure: {α : Type ?u.3794} → α → Computation αa)) (a: ?m.3791h2 : ∀h2: (s : Computation α) → C (think s)s,s: ?m.3800C (C: Computation α → Sort vthinkthink: {α : Type ?u.3803} → Computation α → Computation αs)) :s: ?m.3800CC: Computation α → Sort vs := match H: (s: Computation αdestructdestruct: {α : Type ?u.3812} → Computation α → α ⊕ Computation αs) with | Sum.inls: Computation αv =>v: αGoals accomplished! 🐙α: Type u
β: Type v
γ: Type w
C: Computation α → Sort v
s: Computation α
h1: (a : α) → C (pure a)
h2: (s : Computation α) → C (think s)
v: α
H: destruct s = Sum.inl vC sα: Type u
β: Type v
γ: Type w
C: Computation α → Sort v
s: Computation α
h1: (a : α) → C (pure a)
h2: (s : Computation α) → C (think s)
v: α
H: destruct s = Sum.inl vC sα: Type u
β: Type v
γ: Type w
C: Computation α → Sort v
s: Computation α
h1: (a : α) → C (pure a)
h2: (s : Computation α) → C (think s)
v: α
H: destruct s = Sum.inl vC (pure v)α: Type u
β: Type v
γ: Type w
C: Computation α → Sort v
s: Computation α
h1: (a : α) → C (pure a)
h2: (s : Computation α) → C (think s)
v: α
H: destruct s = Sum.inl vC (pure v)α: Type u
β: Type v
γ: Type w
C: Computation α → Sort v
s: Computation α
h1: (a : α) → C (pure a)
h2: (s : Computation α) → C (think s)
v: α
H: destruct s = Sum.inl vC s| Sum.inrGoals accomplished! 🐙v => matchv: Computation αv with | ⟨a, s'⟩ =>v: Computation αGoals accomplished! 🐙α: Type u
β: Type v
γ: Type w
C: Computation α → Sort v
s: Computation α
h1: (a : α) → C (pure a)
h2: (s : Computation α) → C (think s)
v: Computation α
a: Stream' (Option α)
s': ∀ ⦃n : ℕ⦄ ⦃a_1 : α⦄, a n = some a_1 → a (n + 1) = some a_1
H: destruct s = Sum.inr { val := a, property := s' }C (think { val := a, property := s' })α: Type u
β: Type v
γ: Type w
C: Computation α → Sort v
s: Computation α
h1: (a : α) → C (pure a)
h2: (s : Computation α) → C (think s)
v: Computation α
a: Stream' (Option α)
s': ∀ ⦃n : ℕ⦄ ⦃a_1 : α⦄, a n = some a_1 → a (n + 1) = some a_1
H: destruct s = Sum.inr { val := a, property := s' }C (think { val := a, property := s' })#align computation.rec_onGoals accomplished! 🐙Computation.recOn /-- Corecursor constructor for `corec`-/ def Corec.f (Computation.recOn: {α : Type u} → {C : Computation α → Sort v} → (s : Computation α) → ((a : α) → C (pure a)) → ((s : Computation α) → C (think s)) → C sf :f: β → α ⊕ ββ → Sumβ: Type vαα: Type uβ) : Sumβ: Type vαα: Type uβ → Optionβ: Type vα × Sumα: Type uαα: Type uβ | Sum.inlβ: Type va => (somea: αa, Sum.inla: αa) | Sum.inra: αb => (matchb: βff: β → α ⊕ βb with | Sum.inlb: βa => somea: αa | Sum.inr _ => none,a: αff: β → α ⊕ βb) set_option linter.uppercaseLean3 false in #align computation.corec.F Computation.Corec.f /-- `corec f b` is the corecursor for `Computation α` as a coinductive type. If `f b = inl a` then `corec f b = pure a`, and if `f b = inl b'` then `corec f b = think (corec f b')`. -/ defb: βcorec (corec: {α : Type u} → {β : Type v} → (β → α ⊕ β) → β → Computation αf :f: β → α ⊕ ββ → Sumβ: Type vαα: Type uβ) (β: Type vb :b: ββ) : Computationβ: Type vα :=α: Type uGoals accomplished! 🐙
zero.inl
zero.inr
zero.inl
zero.inr
zero.inl
zero.inrGoals accomplished! 🐙α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
zero.inr(match (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
zero.inr(match (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
x✝: α ⊕ β
a✝: α
heq✝: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd = Sum.inl a✝
zero.inr.h_1α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
x✝: α ⊕ β
val✝: β
heq✝: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd = Sum.inr val✝
zero.inr.h_2α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
zero.inr(match (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
x✝: α ⊕ β
a✝: α
heq✝: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd = Sum.inl a✝
zero.inr.h_1α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
x✝: α ⊕ β
val✝: β
heq✝: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd = Sum.inr val✝
zero.inr.h_2α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b✝: β
a': α
b: β
h: (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'
zero.inr(match (match Sum.inr b with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).snd with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)).fst = some a'Goals accomplished! 🐙α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b: β
a': α
n: ℕ
IH: ∀ (o : α ⊕ β), Stream'.corec' (Corec.f f) o n = some a' → Stream'.corec' (Corec.f f) (Corec.f f o).snd n = some a'
o: α ⊕ β
succStream'.corec' (Corec.f f) o (Nat.succ n) = some a' → Stream'.cons (Corec.f f (Corec.f f o).snd).fst (Stream'.corec' (Corec.f f) (Corec.f f (Corec.f f o).snd).snd) (Nat.succ n) = some a'α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b: β
a': α
n: ℕ
IH: ∀ (o : α ⊕ β), Stream'.corec' (Corec.f f) o n = some a' → Stream'.corec' (Corec.f f) (Corec.f f o).snd n = some a'
o: α ⊕ β
succStream'.cons (Corec.f f o).fst (Stream'.corec' (Corec.f f) (Corec.f f o).snd) (Nat.succ n) = some a' → Stream'.cons (Corec.f f (Corec.f f o).snd).fst (Stream'.corec' (Corec.f f) (Corec.f f (Corec.f f o).snd).snd) (Nat.succ n) = some a'α: Type u
β: Type v
γ: Type w
f: β → α ⊕ β
b: β
a': α
n: ℕ
IH: ∀ (o : α ⊕ β), Stream'.corec' (Corec.f f) o n = some a' → Stream'.corec' (Corec.f f) (Corec.f f o).snd n = some a'
o: α ⊕ β
succStream'.cons (Corec.f f o).fst (Stream'.corec' (Corec.f f) (Corec.f f o).snd) (Nat.succ n) = some a' → Stream'.cons (Corec.f f (Corec.f f o).snd).fst (Stream'.corec' (Corec.f f) (Corec.f f (Corec.f f o).snd).snd) (Nat.succ n) = some a'#align computation.corecGoals accomplished! 🐙Computation.corec /-- left map of `⊕` -/ def lmap (Computation.corec: {α : Type u} → {β : Type v} → (β → α ⊕ β) → β → Computation αf :f: α → βα →α: Type uβ) : Sumβ: Type vαα: Type uγ → Sumγ: Type wββ: Type vγ | Sum.inlγ: Type wa => Sum.inl (a: αff: α → βa) | Sum.inra: αb => Sum.inrb: γb #align computation.lmap Computation.lmap /-- right map of `⊕` -/ def rmap (b: γf :f: β → γβ →β: Type vγ) : Sumγ: Type wαα: Type uβ → Sumβ: Type vαα: Type uγ | Sum.inlγ: Type wa => Sum.inla: αa | Sum.inra: αb => Sum.inr (b: βff: β → γb) #align computation.rmap Computation.rmap attribute [simp] lmap rmap -- porting note: this was far less painful in mathlib3. There seem to be two issues; -- firstly, in mathlib3 we have `corec.F._match_1` and it's the obvious map α ⊕ β → option α. -- In mathlib4 we have `Corec.f.match_1` and it's something completely different. -- Secondly, the proof that `Stream'.corec' (Corec.f f) (Sum.inr b) 0` is this function -- evaluated at `f b`, used to be `rfl` and now is `cases, rfl`. @[simp] theoremb: βcorec_eq (f :f: β → α ⊕ ββ → Sumβ: Type vαα: Type uβ) (β: Type vb :b: ββ) :β: Type vdestruct (destruct: {α : Type ?u.8349} → Computation α → α ⊕ Computation αcoreccorec: {α : Type ?u.8352} → {β : Type ?u.8351} → (β → α ⊕ β) → β → Computation αff: β → α ⊕ βb) = rmap (b: βcoreccorec: {α : Type ?u.8371} → {β : Type ?u.8370} → (β → α ⊕ β) → β → Computation αf) (f: β → α ⊕ βff: β → α ⊕ βb) :=b: βGoals accomplished! 🐙(match Stream'.corec' (Corec.f f) (Sum.inr b) 0 with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match f b with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }(match Stream'.corec' (Corec.f f) (Sum.inr b) 0 with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match f b with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }(match Stream'.corec' (Corec.f f) (Sum.inr b) 0 with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match f b with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }Goals accomplished! 🐙Goals accomplished! 🐙(match Stream'.corec' (Corec.f f) (Sum.inr b) 0 with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match f b with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }(match Sum.rec some (fun x => none) (f b) with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match f b with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }
inl(match Sum.rec some (fun x => none) (Sum.inl a) with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match Sum.inl a with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }
inr(match Sum.rec some (fun x => none) (Sum.inr b') with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match Sum.inr b' with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }
inl(match Sum.rec some (fun x => none) (Sum.inl a) with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match Sum.inl a with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }
inr(match Sum.rec some (fun x => none) (Sum.inr b') with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match Sum.inr b' with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }
inl(match Sum.rec some (fun x => none) (Sum.inl a) with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match Sum.inl a with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }
inl(match Sum.rec some (fun x => none) (Sum.inl a) with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match Sum.inl a with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }
inr(match Sum.rec some (fun x => none) (Sum.inr b') with | none => Sum.inr (tail { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) | some a => Sum.inl a) = match Sum.inr b' with | Sum.inl a => Sum.inl a | Sum.inr b => Sum.inr { val := Stream'.corec' (Corec.f f) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }Goals accomplished! 🐙
inrSum.inr (tail { val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) = Sum.inr { val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b'), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b') n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b') (n + 1) = some a') }
inr.htail { val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') } = { val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b'), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b') n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b') (n + 1) = some a') }
inr.htail { val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') } = { val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b'), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b') n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b') (n + 1) = some a') }
inr.h.a↑(tail { val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b) n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b) (n + 1) = some a') }) = ↑{ val := Stream'.corec' (fun x => match x with | Sum.inl a => (some a, Sum.inl a) | Sum.inr b => (match f b with | Sum.inl a => some a | Sum.inr val => none, f b)) (Sum.inr b'), property := (_ : ∀ (n : ℕ) (a' : α), Stream'.corec' (Corec.f f) (Sum.inr b') n = some a' → Stream'.corec' (Corec.f f) (Sum.inr b') (n + 1) = some a') }