File: Mathlib/Data/Seq/Computation.lean

full_name: Computation
code: /-- `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 u) : Type u 
goal: Type u

full_name: Computation.pure
code: /-- `pure a` is the computation that immediately terminates with result `a`. -/
-- Porting note: `return` is reserved, so changed to `pure`
def pure (a : α) : Computation α 
goal: Computation α

full_name: Computation.instCoeTC
code: instance : CoeTC α (Computation α) 
goal: CoeTC α (Computation α)

full_name: Computation.think
code: /-- `think c` is the computation that delays for one "tick" and then performs
  computation `c`. -/
def think (c : Computation α) : Computation α 
goal: Computation α

full_name: Computation.thinkN
code: /-- `thinkN c n` is the computation that delays for `n` ticks and then performs
  computation `c`. -/
def thinkN (c : Computation α) : ℕ → Computation α
  
goal: ℕ → Computation α

full_name: Computation.head
code: /-- `head c` is the first step of computation, either `some a` if `c = pure a`
  or `none` if `c = think c'`. -/
def head (c : Computation α) : Option α 
goal: Option α

full_name: Computation.tail
code: /-- `tail c` is the remainder of computation, either `c` if `c = pure a`
  or `c'` if `c = think c'`. -/
def tail (c : Computation α) : Computation α 
goal: Computation α

full_name: Computation.empty
code: /-- `empty α` is the computation that never returns, an infinite sequence of
  `think`s. -/
def empty (α) : Computation α 
goal: Computation α

full_name: Computation.instInhabited
code: instance : Inhabited (Computation α) 
goal: Inhabited (Computation α)

full_name: Computation.runFor
code: /-- `runFor c n` evaluates `c` for `n` steps and returns the result, or `none`
  if it did not terminate after `n` steps. -/
def runFor : Computation α → ℕ → Option α 
goal: Computation α → ℕ → Option α

full_name: Computation.destruct
code: /-- `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'`. -/
def destruct (c : Computation α) : α ⊕ (Computation α) 
goal: α ⊕ Computation α

full_name: Computation.run
code: /-- `run c` is an unsound meta function that runs `c` to completion, possibly
  resulting in an infinite loop in the VM. -/
unsafe def run : Computation α → α
  
goal: Computation α → α

full_name: Computation.destruct_eq_pure
code: theorem destruct_eq_pure {s : Computation α} {a : α} : destruct s = Sum.inl a → s = pure a 
goal: s.destruct = Sum.inl a → s = Computation.pure a

full_name: Computation.destruct_eq_think
code: theorem destruct_eq_think {s : Computation α} {s'} : destruct s = Sum.inr s' → s = think s' 
goal: s.destruct = Sum.inr s' → s = s'.think

full_name: Computation.destruct_pure
code: @[simp]
theorem destruct_pure (a : α) : destruct (pure a) = Sum.inl a 
goal: (Computation.pure a).destruct = Sum.inl a

full_name: Computation.destruct_think
code: @[simp]
theorem destruct_think : ∀ s : Computation α, destruct (think s) = Sum.inr s
  
goal: s.think.destruct = Sum.inr s

full_name: Computation.destruct_empty
code: @[simp]
theorem destruct_empty : destruct (empty α) = Sum.inr (empty α) 
goal: (Computation.empty α).destruct = Sum.inr (Computation.empty α)

full_name: Computation.head_pure
code: @[simp]
theorem head_pure (a : α) : head (pure a) = some a 
goal: (Computation.pure a).head = some a

full_name: Computation.head_think
code: @[simp]
theorem head_think (s : Computation α) : head (think s) = none 
goal: s.think.head = none

full_name: Computation.head_empty
code: @[simp]
theorem head_empty : head (empty α) = none 
goal: (Computation.empty α).head = none

full_name: Computation.tail_pure
code: @[simp]
theorem tail_pure (a : α) : tail (pure a) = pure a 
goal: (Computation.pure a).tail = Computation.pure a

full_name: Computation.tail_think
code: @[simp]
theorem tail_think (s : Computation α) : tail (think s) = s 
goal: s.think.tail = s

full_name: Computation.tail_empty
code: @[simp]
theorem tail_empty : tail (empty α) = empty α 
goal: (Computation.empty α).tail = Computation.empty α

full_name: Computation.think_empty
code: theorem think_empty : empty α = think (empty α) 
goal: Computation.empty α = (Computation.empty α).think

full_name: Computation.recOn
code: /-- Recursion principle for computations, compare with `List.recOn`. -/
def recOn {C : Computation α → Sort v} (s : Computation α) (h1 : ∀ a, C (pure a))
    (h2 : ∀ s, C (think s)) : C s 
goal: C s

full_name: Computation.Corec.f
code: /-- Corecursor constructor for `corec`-/
def Corec.f (f : β → α ⊕ β) : α ⊕ β → Option α × (α ⊕ β)
  
goal: α ⊕ β → Option α × (α ⊕ β)

full_name: Computation.corec
code: /-- `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')`. -/
def corec (f : β → α ⊕ β) (b : β) : Computation α 
goal: Computation α

full_name: Computation.lmap
code: /-- left map of `⊕` -/
def lmap (f : α → β) : α ⊕ γ → β ⊕ γ
  
goal: α ⊕ γ → β ⊕ γ

full_name: Computation.rmap
code: /-- right map of `⊕` -/
def rmap (f : β → γ) : α ⊕ β → α ⊕ γ
  
goal: α ⊕ β → α ⊕ γ

full_name: Computation.corec_eq
code: @[simp]
theorem corec_eq (f : β → α ⊕ β) (b : β) : destruct (corec f b) = rmap (corec f) (f b) 
goal: (Computation.corec f b).destruct = Computation.rmap (Computation.corec f) (f b)

full_name: Computation.«_aux_Mathlib_Data_Seq_Computation___macroRules_Computation_term_~__1»
code: /-- bisimilarity relation-/
local infixl:50 " ~ " => R
goal: Lean.Macro

full_name: Computation.BisimO
code: /-- Bisimilarity over a sum of `Computation`s-/
def BisimO : α ⊕ (Computation α) → α ⊕ (Computation α) → Prop
  
goal: α ⊕ Computation α → α ⊕ Computation α → Prop

full_name: Computation.IsBisimulation
code: /-- Attribute expressing bisimilarity over two `Computation`s-/
def IsBisimulation 
goal: Prop

full_name: Computation.eq_of_bisim
code: theorem eq_of_bisim (bisim : IsBisimulation R) {s₁ s₂} (r : s₁ ~ s₂) : s₁ = s₂ 
goal: s₁ = s₂

full_name: Computation.Mem
code: /-- Assertion that a `Computation` limits to a given value-/
protected def Mem (a : α) (s : Computation α) 
goal: Prop

full_name: Computation.instMembership
code: instance : Membership α (Computation α) 
goal: Membership α (Computation α)

full_name: Computation.le_stable
code: theorem le_stable (s : Computation α) {a m n} (h : m ≤ n) : s.1 m = some a → s.1 n = some a 
goal: ↑s m = some a → ↑s n = some a

full_name: Computation.mem_unique
code: theorem mem_unique {s : Computation α} {a b : α} : a ∈ s → b ∈ s → a = b
  
goal: a ∈ s → b ∈ s → a = b

full_name: Computation.Mem.left_unique
code: theorem Mem.left_unique : Relator.LeftUnique ((· ∈ ·) : α → Computation α → Prop) 
goal: Relator.LeftUnique fun x x_1 => x ∈ x_1

full_name: Computation.Terminates
code: /-- `Terminates s` asserts that the computation `s` eventually terminates with some value. -/
class Terminates (s : Computation α) : Prop where
  /-- assertion that there is some term `a` such that the `Computation` terminates -/
  term : ∃ a, a ∈ s
goal: Prop

full_name: Computation.Terminates.term
code: /-- `Terminates s` asserts that the computation `s` eventually terminates with some value. -/
class Terminates (s : Computation α) : Prop where
  /-- assertion that there is some term `a` such that the `Computation` terminates -/
  term : ∃ a, a ∈ s
goal: ∃ a, a ∈ s

full_name: Computation.terminates_iff
code: theorem terminates_iff (s : Computation α) : Terminates s ↔ ∃ a, a ∈ s 
goal: s.Terminates ↔ ∃ a, a ∈ s

full_name: Computation.terminates_of_mem
code: theorem terminates_of_mem {s : Computation α} {a : α} (h : a ∈ s) : Terminates s 
goal: s.Terminates

full_name: Computation.terminates_def
code: theorem terminates_def (s : Computation α) : Terminates s ↔ ∃ n, (s.1 n).isSome 
goal: s.Terminates ↔ ∃ n, (↑s n).isSome = true

full_name: Computation.ret_mem
code: theorem ret_mem (a : α) : a ∈ pure a 
goal: a ∈ Computation.pure a

full_name: Computation.eq_of_pure_mem
code: theorem eq_of_pure_mem {a a' : α} (h : a' ∈ pure a) : a' = a 
goal: a' = a

full_name: Computation.ret_terminates
code: instance ret_terminates (a : α) : Terminates (pure a) 
goal: (Computation.pure a).Terminates

full_name: Computation.think_mem
code: theorem think_mem {s : Computation α} {a} : a ∈ s → a ∈ think s
  
goal: a ∈ s → a ∈ s.think

full_name: Computation.think_terminates
code: instance think_terminates (s : Computation α) : ∀ [Terminates s], Terminates (think s)
  
goal: s.think.Terminates

full_name: Computation.of_think_mem
code: theorem of_think_mem {s : Computation α} {a} : a ∈ think s → a ∈ s
  
goal: a ∈ s.think → a ∈ s

full_name: Computation.of_think_terminates
code: theorem of_think_terminates {s : Computation α} : Terminates (think s) → Terminates s
  
goal: s.think.Terminates → s.Terminates

full_name: Computation.not_mem_empty
code: theorem not_mem_empty (a : α) : a ∉ empty α 
goal: ¬a ∈ Computation.empty α

full_name: Computation.not_terminates_empty
code: theorem not_terminates_empty : ¬Terminates (empty α) 
goal: ¬(Computation.empty α).Terminates

full_name: Computation.eq_empty_of_not_terminates
code: theorem eq_empty_of_not_terminates {s} (H : ¬Terminates s) : s = empty α 
goal: s = Computation.empty α

full_name: Computation.thinkN_mem
code: theorem thinkN_mem {s : Computation α} {a} : ∀ n, a ∈ thinkN s n ↔ a ∈ s
  
goal: a ∈ s.thinkN n ↔ a ∈ s

full_name: Computation.thinkN_terminates
code: instance thinkN_terminates (s : Computation α) : ∀ [Terminates s] (n), Terminates (thinkN s n)
  
goal: (s.thinkN n).Terminates

full_name: Computation.of_thinkN_terminates
code: theorem of_thinkN_terminates (s : Computation α) (n) : Terminates (thinkN s n) → Terminates s
  
goal: (s.thinkN n).Terminates → s.Terminates

full_name: Computation.Promises
code: /-- `Promises s a`, or `s ~> a`, asserts that although the computation `s`
  may not terminate, if it does, then the result is `a`. -/
def Promises (s : Computation α) (a : α) : Prop 
goal: Prop

full_name: Computation.«_aux_Mathlib_Data_Seq_Computation___macroRules_Computation_term_~>__1»
code: /-- `Promises s a`, or `s ~> a`, asserts that although the computation `s`
  may not terminate, if it does, then the result is `a`. -/
scoped infixl:50 " ~> " => Promises
goal: Lean.Macro

full_name: Computation._aux_Mathlib_Data_Seq_Computation___unexpand_Computation_Promises_1
code: /-- `Promises s a`, or `s ~> a`, asserts that although the computation `s`
  may not terminate, if it does, then the result is `a`. -/
scoped infixl:50 " ~> " => Promises
goal: Lean.PrettyPrinter.Unexpander

full_name: Computation.mem_promises
code: theorem mem_promises {s : Computation α} {a : α} : a ∈ s → s ~> a 
goal: a ∈ s → s.Promises a

full_name: Computation.empty_promises
code: theorem empty_promises (a : α) : empty α ~> a 
goal: (Computation.empty α).Promises a

full_name: Computation.length
code: /-- `length s` gets the number of steps of a terminating computation -/
def length : ℕ 
goal: ℕ

full_name: Computation.get
code: /-- `get s` returns the result of a terminating computation -/
def get : α 
goal: α

full_name: Computation.get_mem
code: theorem get_mem : get s ∈ s 
goal: s.get ∈ s

full_name: Computation.get_eq_of_mem
code: theorem get_eq_of_mem {a} : a ∈ s → get s = a 
goal: a ∈ s → s.get = a

full_name: Computation.mem_of_get_eq
code: theorem mem_of_get_eq {a} : get s = a → a ∈ s 
goal: s.get = a → a ∈ s

full_name: Computation.get_think
code: @[simp]
theorem get_think : get (think s) = get s 
goal: s.think.get = s.get

full_name: Computation.get_thinkN
code: @[simp]
theorem get_thinkN (n) : get (thinkN s n) = get s 
goal: (s.thinkN n).get = s.get

full_name: Computation.get_promises
code: theorem get_promises : s ~> get s 
goal: s.Promises s.get

full_name: Computation.mem_of_promises
code: theorem mem_of_promises {a} (p : s ~> a) : a ∈ s 
goal: a ∈ s

full_name: Computation.get_eq_of_promises
code: theorem get_eq_of_promises {a} : s ~> a → get s = a 
goal: s.Promises a → s.get = a

full_name: Computation.Results
code: /-- `Results s a n` completely characterizes a terminating computation:
  it asserts that `s` terminates after exactly `n` steps, with result `a`. -/
def Results (s : Computation α) (a : α) (n : ℕ) 
goal: Prop

full_name: Computation.results_of_terminates
code: theorem results_of_terminates (s : Computation α) [_T : Terminates s] :
    Results s (get s) (length s) 
goal: s.Results s.get s.length

full_name: Computation.results_of_terminates'
code: theorem results_of_terminates' (s : Computation α) [T : Terminates s] {a} (h : a ∈ s) :
    Results s a (length s) 
goal: s.Results a s.length

full_name: Computation.Results.mem
code: theorem Results.mem {s : Computation α} {a n} : Results s a n → a ∈ s
  
goal: s.Results a n → a ∈ s

full_name: Computation.Results.terminates
code: theorem Results.terminates {s : Computation α} {a n} (h : Results s a n) : Terminates s 
goal: s.Terminates

full_name: Computation.Results.length
code: theorem Results.length {s : Computation α} {a n} [_T : Terminates s] : Results s a n → length s = n
  
goal: s.Results a n → s.length = n

full_name: Computation.Results.val_unique
code: theorem Results.val_unique {s : Computation α} {a b m n} (h1 : Results s a m) (h2 : Results s b n) :
    a = b 
goal: a = b

full_name: Computation.Results.len_unique
code: theorem Results.len_unique {s : Computation α} {a b m n} (h1 : Results s a m) (h2 : Results s b n) :
    m = n 
goal: m = n

full_name: Computation.exists_results_of_mem
code: theorem exists_results_of_mem {s : Computation α} {a} (h : a ∈ s) : ∃ n, Results s a n 
goal: ∃ n, s.Results a n

full_name: Computation.get_pure
code: @[simp]
theorem get_pure (a : α) : get (pure a) = a 
goal: (Computation.pure a).get = a

full_name: Computation.length_pure
code: @[simp]
theorem length_pure (a : α) : length (pure a) = 0 
goal: (Computation.pure a).length = 0

full_name: Computation.results_pure
code: theorem results_pure (a : α) : Results (pure a) a 0 
goal: (Computation.pure a).Results a 0

full_name: Computation.length_think
code: @[simp]
theorem length_think (s : Computation α) [h : Terminates s] : length (think s) = length s + 1 
goal: s.think.length = s.length + 1

full_name: Computation.results_think
code: theorem results_think {s : Computation α} {a n} (h : Results s a n) : Results (think s) a (n + 1) 
goal: s.think.Results a (n + 1)

full_name: Computation.of_results_think
code: theorem of_results_think {s : Computation α} {a n} (h : Results (think s) a n) :
    ∃ m, Results s a m ∧ n = m + 1 
goal: ∃ m, s.Results a m ∧ n = m + 1

full_name: Computation.results_think_iff
code: @[simp]
theorem results_think_iff {s : Computation α} {a n} : Results (think s) a (n + 1) ↔ Results s a n 
goal: s.think.Results a (n + 1) ↔ s.Results a n

full_name: Computation.results_thinkN
code: theorem results_thinkN {s : Computation α} {a m} :
    ∀ n, Results s a m → Results (thinkN s n) a (m + n)
  
goal: s.Results a m → (s.thinkN n).Results a (m + n)

full_name: Computation.results_thinkN_pure
code: theorem results_thinkN_pure (a : α) (n) : Results (thinkN (pure a) n) a n 
goal: ((Computation.pure a).thinkN n).Results a n

full_name: Computation.length_thinkN
code: @[simp]
theorem length_thinkN (s : Computation α) [_h : Terminates s] (n) :
    length (thinkN s n) = length s + n 
goal: (s.thinkN n).length = s.length + n

full_name: Computation.eq_thinkN
code: theorem eq_thinkN {s : Computation α} {a n} (h : Results s a n) : s = thinkN (pure a) n 
goal: s = (Computation.pure a).thinkN n

full_name: Computation.eq_thinkN'
code: theorem eq_thinkN' (s : Computation α) [_h : Terminates s] :
    s = thinkN (pure (get s)) (length s) 
goal: s = (Computation.pure s.get).thinkN s.length

full_name: Computation.memRecOn
code: /-- Recursor based on membership-/
def memRecOn {C : Computation α → Sort v} {a s} (M : a ∈ s) (h1 : C (pure a))
    (h2 : ∀ s, C s → C (think s)) : C s 
goal: C s

full_name: Computation.terminatesRecOn
code: /-- Recursor based on assertion of `Terminates`-/
def terminatesRecOn
    {C : Computation α → Sort v}
    (s) [Terminates s]
    (h1 : ∀ a, C (pure a))
    (h2 : ∀ s, C s → C (think s)) : C s 
goal: C s

full_name: Computation.map
code: /-- Map a function on the result of a computation. -/
def map (f : α → β) : Computation α → Computation β
  
goal: Computation α → Computation β

full_name: Computation.Bind.g
code: /-- bind over a `Sum` of `Computation`-/
def Bind.g : β ⊕ Computation β → β ⊕ (Computation α ⊕ Computation β)
  
goal: β ⊕ Computation β → β ⊕ Computation α ⊕ Computation β

full_name: Computation.Bind.f
code: /-- bind over a function mapping `α` to a `Computation`-/
def Bind.f (f : α → Computation β) :
    Computation α ⊕ Computation β → β ⊕ (Computation α ⊕ Computation β)
  
goal: Computation α ⊕ Computation β → β ⊕ Computation α ⊕ Computation β

full_name: Computation.bind
code: /-- Compose two computations into a monadic `bind` operation. -/
def bind (c : Computation α) (f : α → Computation β) : Computation β 
goal: Computation β

full_name: Computation.instBind
code: instance : Bind Computation 
goal: Bind Computation

full_name: Computation.has_bind_eq_bind
code: theorem has_bind_eq_bind {β} (c : Computation α) (f : α → Computation β) : c >>= f = bind c f 
goal: c >>= f = c.bind f

full_name: Computation.join
code: /-- Flatten a computation of computations into a single computation. -/
def join (c : Computation (Computation α)) : Computation α 
goal: Computation α

full_name: Computation.map_pure
code: @[simp]
theorem map_pure (f : α → β) (a) : map f (pure a) = pure (f a) 
goal: Computation.map f (Computation.pure a) = Computation.pure (f a)

full_name: Computation.map_think
code: @[simp]
theorem map_think (f : α → β) : ∀ s, map f (think s) = think (map f s)
  
goal: Computation.map f s.think = (Computation.map f s).think

full_name: Computation.destruct_map
code: @[simp]
theorem destruct_map (f : α → β) (s) : destruct (map f s) = lmap f (rmap (map f) (destruct s)) 
goal: (Computation.map f s).destruct = Computation.lmap f (Computation.rmap (Computation.map f) s.destruct)

full_name: Computation.map_id
code: @[simp]
theorem map_id : ∀ s : Computation α, map id s = s
  
goal: Computation.map id s = s

full_name: Computation.map_comp
code: theorem map_comp (f : α → β) (g : β → γ) : ∀ s : Computation α, map (g ∘ f) s = map g (map f s)
  
goal: Computation.map (g ∘ f) s = Computation.map g (Computation.map f s)

full_name: Computation.ret_bind
code: @[simp]
theorem ret_bind (a) (f : α → Computation β) : bind (pure a) f = f a 
goal: (Computation.pure a).bind f = f a

full_name: Computation.think_bind
code: @[simp]
theorem think_bind (c) (f : α → Computation β) : bind (think c) f = think (bind c f) 
goal: c.think.bind f = (c.bind f).think

full_name: Computation.bind_pure
code: @[simp]
theorem bind_pure (f : α → β) (s) : bind s (pure ∘ f) = map f s 
goal: s.bind (Computation.pure ∘ f) = Computation.map f s

full_name: Computation.bind_pure'
code: @[simp]
theorem bind_pure' (s : Computation α) : bind s pure = s 
goal: s.bind Computation.pure = s

full_name: Computation.bind_assoc
code: @[simp]
theorem bind_assoc (s : Computation α) (f : α → Computation β) (g : β → Computation γ) :
    bind (bind s f) g = bind s fun x : α => bind (f x) g 
goal: (s.bind f).bind g = s.bind fun x => (f x).bind g

full_name: Computation.results_bind
code: theorem results_bind {s : Computation α} {f : α → Computation β} {a b m n} (h1 : Results s a m)
    (h2 : Results (f a) b n) : Results (bind s f) b (n + m) 
goal: (s.bind f).Results b (n + m)

full_name: Computation.mem_bind
code: theorem mem_bind {s : Computation α} {f : α → Computation β} {a b} (h1 : a ∈ s) (h2 : b ∈ f a) :
    b ∈ bind s f 
goal: b ∈ s.bind f

full_name: Computation.terminates_bind
code: instance terminates_bind (s : Computation α) (f : α → Computation β) [Terminates s]
    [Terminates (f (get s))] : Terminates (bind s f) 
goal: (s.bind f).Terminates

full_name: Computation.get_bind
code: @[simp]
theorem get_bind (s : Computation α) (f : α → Computation β) [Terminates s]
    [Terminates (f (get s))] : get (bind s f) = get (f (get s)) 
goal: (s.bind f).get = (f s.get).get

full_name: Computation.length_bind
code: @[simp]
theorem length_bind (s : Computation α) (f : α → Computation β) [_T1 : Terminates s]
    [_T2 : Terminates (f (get s))] : length (bind s f) = length (f (get s)) + length s 
goal: (s.bind f).length = (f s.get).length + s.length

full_name: Computation.of_results_bind
code: theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} :
    Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m 
goal: (s.bind f).Results b k → ∃ a m n, s.Results a m ∧ (f a).Results b n ∧ k = n + m

full_name: Computation.exists_of_mem_bind
code: theorem exists_of_mem_bind {s : Computation α} {f : α → Computation β} {b} (h : b ∈ bind s f) :
    ∃ a ∈ s, b ∈ f a 
goal: ∃ a, a ∈ s ∧ b ∈ f a

full_name: Computation.bind_promises
code: theorem bind_promises {s : Computation α} {f : α → Computation β} {a b} (h1 : s ~> a)
    (h2 : f a ~> b) : bind s f ~> b 
goal: (s.bind f).Promises b

full_name: Computation.monad
code: instance monad : Monad Computation 
goal: Monad Computation

full_name: Computation.instLawfulMonad
code: instance : LawfulMonad Computation 
goal: LawfulMonad Computation

full_name: Computation.has_map_eq_map
code: theorem has_map_eq_map {β} (f : α → β) (c : Computation α) : f <$> c = map f c 
goal: f <$> c = Computation.map f c

full_name: Computation.pure_def
code: @[simp]
theorem pure_def (a) : (return a : Computation α) = pure a 
goal: pure a = Computation.pure a

full_name: Computation.map_pure'
code: @[simp]
theorem map_pure' {α β} : ∀ (f : α → β) (a), f <$> pure a = pure (f a) 
goal: f <$> Computation.pure a = Computation.pure (f a)

full_name: Computation.map_think'
code: @[simp]
theorem map_think' {α β} : ∀ (f : α → β) (s), f <$> think s = think (f <$> s) 
goal: f <$> s.think = (f <$> s).think

full_name: Computation.mem_map
code: theorem mem_map (f : α → β) {a} {s : Computation α} (m : a ∈ s) : f a ∈ map f s 
goal: f a ∈ Computation.map f s

full_name: Computation.exists_of_mem_map
code: theorem exists_of_mem_map {f : α → β} {b : β} {s : Computation α} (h : b ∈ map f s) :
    ∃ a, a ∈ s ∧ f a = b 
goal: ∃ a, a ∈ s ∧ f a = b

full_name: Computation.terminates_map
code: instance terminates_map (f : α → β) (s : Computation α) [Terminates s] : Terminates (map f s) 
goal: (Computation.map f s).Terminates

full_name: Computation.terminates_map_iff
code: theorem terminates_map_iff (f : α → β) (s : Computation α) : Terminates (map f s) ↔ Terminates s 
goal: (Computation.map f s).Terminates ↔ s.Terminates

full_name: Computation.orElse
code: /-- `c₁ <|> c₂` calculates `c₁` and `c₂` simultaneously, returning
  the first one that gives a result. -/
def orElse (c₁ : Computation α) (c₂ : Unit → Computation α) : Computation α 
goal: Computation α

full_name: Computation.instAlternativeComputation
code: instance instAlternativeComputation : Alternative Computation 
goal: Alternative Computation

full_name: Computation.ret_orElse
code: @[simp]
theorem ret_orElse (a : α) (c₂ : Computation α) : (pure a <|> c₂) = pure a 
goal: (HOrElse.hOrElse (Computation.pure a) fun x => c₂) = Computation.pure a

full_name: Computation.orElse_pure
code: @[simp]
theorem orElse_pure (c₁ : Computation α) (a : α) : (think c₁ <|> pure a) = pure a 
goal: (HOrElse.hOrElse c₁.think fun x => Computation.pure a) = Computation.pure a

full_name: Computation.orElse_think
code: @[simp]
theorem orElse_think (c₁ c₂ : Computation α) : (think c₁ <|> think c₂) = think (c₁ <|> c₂) 
goal: (HOrElse.hOrElse c₁.think fun x => c₂.think) = (HOrElse.hOrElse c₁ fun x => c₂).think

full_name: Computation.empty_orElse
code: @[simp]
theorem empty_orElse (c) : (empty α <|> c) = c 
goal: (HOrElse.hOrElse (Computation.empty α) fun x => c) = c

full_name: Computation.orElse_empty
code: @[simp]
theorem orElse_empty (c : Computation α) : (c <|> empty α) = c 
goal: (HOrElse.hOrElse c fun x => Computation.empty α) = c

full_name: Computation.Equiv
code: /-- `c₁ ~ c₂` asserts that `c₁` and `c₂` either both terminate with the same result,
  or both loop forever. -/
def Equiv (c₁ c₂ : Computation α) : Prop 
goal: Prop

full_name: Computation.«_aux_Mathlib_Data_Seq_Computation___macroRules_Computation_term_~__2»
code: /-- equivalence relation for computations-/
scoped infixl:50 " ~ " => Equiv
goal: Lean.Macro

full_name: Computation._aux_Mathlib_Data_Seq_Computation___unexpand_Computation_Equiv_1
code: /-- equivalence relation for computations-/
scoped infixl:50 " ~ " => Equiv
goal: Lean.PrettyPrinter.Unexpander

full_name: Computation.Equiv.refl
code: @[refl]
theorem Equiv.refl (s : Computation α) : s ~ s 
goal: s.Equiv s

full_name: Computation.Equiv.symm
code: @[symm]
theorem Equiv.symm {s t : Computation α} : s ~ t → t ~ s 
goal: s.Equiv t → t.Equiv s

full_name: Computation.Equiv.trans
code: @[trans]
theorem Equiv.trans {s t u : Computation α} : s ~ t → t ~ u → s ~ u 
goal: s.Equiv t → t.Equiv u → s.Equiv u

full_name: Computation.Equiv.equivalence
code: theorem Equiv.equivalence : Equivalence (@Equiv α) 
goal: Equivalence Computation.Equiv

full_name: Computation.equiv_of_mem
code: theorem equiv_of_mem {s t : Computation α} {a} (h1 : a ∈ s) (h2 : a ∈ t) : s ~ t 
goal: s.Equiv t

full_name: Computation.terminates_congr
code: theorem terminates_congr {c₁ c₂ : Computation α} (h : c₁ ~ c₂) : Terminates c₁ ↔ Terminates c₂ 
goal: c₁.Terminates ↔ c₂.Terminates

full_name: Computation.promises_congr
code: theorem promises_congr {c₁ c₂ : Computation α} (h : c₁ ~ c₂) (a) : c₁ ~> a ↔ c₂ ~> a 
goal: c₁.Promises a ↔ c₂.Promises a

full_name: Computation.get_equiv
code: theorem get_equiv {c₁ c₂ : Computation α} (h : c₁ ~ c₂) [Terminates c₁] [Terminates c₂] :
    get c₁ = get c₂ 
goal: c₁.get = c₂.get

full_name: Computation.think_equiv
code: theorem think_equiv (s : Computation α) : think s ~ s 
goal: s.think.Equiv s

full_name: Computation.thinkN_equiv
code: theorem thinkN_equiv (s : Computation α) (n) : thinkN s n ~ s 
goal: (s.thinkN n).Equiv s

full_name: Computation.bind_congr
code: theorem bind_congr {s1 s2 : Computation α} {f1 f2 : α → Computation β} (h1 : s1 ~ s2)
    (h2 : ∀ a, f1 a ~ f2 a) : bind s1 f1 ~ bind s2 f2 
goal: (s1.bind f1).Equiv (s2.bind f2)

full_name: Computation.equiv_pure_of_mem
code: theorem equiv_pure_of_mem {s : Computation α} {a} (h : a ∈ s) : s ~ pure a 
goal: s.Equiv (Computation.pure a)

full_name: Computation.LiftRel
code: /-- `LiftRel R ca cb` is a generalization of `Equiv` to relations other than
  equality. It asserts that if `ca` terminates with `a`, then `cb` terminates with
  some `b` such that `R a b`, and if `cb` terminates with `b` then `ca` terminates
  with some `a` such that `R a b`. -/
def LiftRel (R : α → β → Prop) (ca : Computation α) (cb : Computation β) : Prop 
goal: Prop

full_name: Computation.LiftRel.swap
code: theorem LiftRel.swap (R : α → β → Prop) (ca : Computation α) (cb : Computation β) :
    LiftRel (swap R) cb ca ↔ LiftRel R ca cb 
goal: Computation.LiftRel (Function.swap R) cb ca ↔ Computation.LiftRel R ca cb

full_name: Computation.lift_eq_iff_equiv
code: theorem lift_eq_iff_equiv (c₁ c₂ : Computation α) : LiftRel (· = ·) c₁ c₂ ↔ c₁ ~ c₂ 
goal: Computation.LiftRel (fun x x_1 => x = x_1) c₁ c₂ ↔ c₁.Equiv c₂

full_name: Computation.LiftRel.refl
code: theorem LiftRel.refl (R : α → α → Prop) (H : Reflexive R) : Reflexive (LiftRel R) 
goal: Reflexive (Computation.LiftRel R)

full_name: Computation.LiftRel.symm
code: theorem LiftRel.symm (R : α → α → Prop) (H : Symmetric R) : Symmetric (LiftRel R) 
goal: Symmetric (Computation.LiftRel R)

full_name: Computation.LiftRel.trans
code: theorem LiftRel.trans (R : α → α → Prop) (H : Transitive R) : Transitive (LiftRel R) 
goal: Transitive (Computation.LiftRel R)

full_name: Computation.LiftRel.equiv
code: theorem LiftRel.equiv (R : α → α → Prop) : Equivalence R → Equivalence (LiftRel R)
  
goal: Equivalence R → Equivalence (Computation.LiftRel R)

full_name: Computation.LiftRel.imp
code: theorem LiftRel.imp {R S : α → β → Prop} (H : ∀ {a b}, R a b → S a b) (s t) :
    LiftRel R s t → LiftRel S s t
  
goal: Computation.LiftRel R s t → Computation.LiftRel S s t

full_name: Computation.terminates_of_liftRel
code: theorem terminates_of_liftRel {R : α → β → Prop} {s t} :
    LiftRel R s t → (Terminates s ↔ Terminates t)
  
goal: Computation.LiftRel R s t → (s.Terminates ↔ t.Terminates)

full_name: Computation.rel_of_liftRel
code: theorem rel_of_liftRel {R : α → β → Prop} {ca cb} :
    LiftRel R ca cb → ∀ {a b}, a ∈ ca → b ∈ cb → R a b
  
goal: Computation.LiftRel R ca cb → ∀ {a : α} {b : β}, a ∈ ca → b ∈ cb → R a b

full_name: Computation.liftRel_of_mem
code: theorem liftRel_of_mem {R : α → β → Prop} {a b ca cb} (ma : a ∈ ca) (mb : b ∈ cb) (ab : R a b) :
    LiftRel R ca cb 
goal: Computation.LiftRel R ca cb

full_name: Computation.exists_of_liftRel_left
code: theorem exists_of_liftRel_left {R : α → β → Prop} {ca cb} (H : LiftRel R ca cb) {a} (h : a ∈ ca) :
    ∃ b, b ∈ cb ∧ R a b 
goal: ∃ b, b ∈ cb ∧ R a b

full_name: Computation.exists_of_liftRel_right
code: theorem exists_of_liftRel_right {R : α → β → Prop} {ca cb} (H : LiftRel R ca cb) {b} (h : b ∈ cb) :
    ∃ a, a ∈ ca ∧ R a b 
goal: ∃ a, a ∈ ca ∧ R a b

full_name: Computation.liftRel_def
code: theorem liftRel_def {R : α → β → Prop} {ca cb} :
    LiftRel R ca cb ↔ (Terminates ca ↔ Terminates cb) ∧ ∀ {a b}, a ∈ ca → b ∈ cb → R a b 
goal: Computation.LiftRel R ca cb ↔ (ca.Terminates ↔ cb.Terminates) ∧ ∀ {a : α} {b : β}, a ∈ ca → b ∈ cb → R a b

full_name: Computation.liftRel_bind
code: theorem liftRel_bind {δ} (R : α → β → Prop) (S : γ → δ → Prop) {s1 : Computation α}
    {s2 : Computation β} {f1 : α → Computation γ} {f2 : β → Computation δ} (h1 : LiftRel R s1 s2)
    (h2 : ∀ {a b}, R a b → LiftRel S (f1 a) (f2 b)) : LiftRel S (bind s1 f1) (bind s2 f2) 
goal: Computation.LiftRel S (s1.bind f1) (s2.bind f2)

full_name: Computation.liftRel_pure_left
code: @[simp]
theorem liftRel_pure_left (R : α → β → Prop) (a : α) (cb : Computation β) :
    LiftRel R (pure a) cb ↔ ∃ b, b ∈ cb ∧ R a b 
goal: Computation.LiftRel R (Computation.pure a) cb ↔ ∃ b, b ∈ cb ∧ R a b

full_name: Computation.liftRel_pure_right
code: @[simp]
theorem liftRel_pure_right (R : α → β → Prop) (ca : Computation α) (b : β) :
    LiftRel R ca (pure b) ↔ ∃ a, a ∈ ca ∧ R a b 
goal: Computation.LiftRel R ca (Computation.pure b) ↔ ∃ a, a ∈ ca ∧ R a b

full_name: Computation.liftRel_pure
code: @[simp, nolint simpNF]
theorem liftRel_pure (R : α → β → Prop) (a : α) (b : β) :
    LiftRel R (pure a) (pure b) ↔ R a b 
goal: Computation.LiftRel R (Computation.pure a) (Computation.pure b) ↔ R a b

full_name: Computation.liftRel_think_left
code: @[simp]
theorem liftRel_think_left (R : α → β → Prop) (ca : Computation α) (cb : Computation β) :
    LiftRel R (think ca) cb ↔ LiftRel R ca cb 
goal: Computation.LiftRel R ca.think cb ↔ Computation.LiftRel R ca cb

full_name: Computation.liftRel_think_right
code: @[simp]
theorem liftRel_think_right (R : α → β → Prop) (ca : Computation α) (cb : Computation β) :
    LiftRel R ca (think cb) ↔ LiftRel R ca cb 
goal: Computation.LiftRel R ca cb.think ↔ Computation.LiftRel R ca cb

full_name: Computation.liftRel_mem_cases
code: theorem liftRel_mem_cases {R : α → β → Prop} {ca cb} (Ha : ∀ a ∈ ca, LiftRel R ca cb)
    (Hb : ∀ b ∈ cb, LiftRel R ca cb) : LiftRel R ca cb 
goal: Computation.LiftRel R ca cb

full_name: Computation.liftRel_congr
code: theorem liftRel_congr {R : α → β → Prop} {ca ca' : Computation α} {cb cb' : Computation β}
    (ha : ca ~ ca') (hb : cb ~ cb') : LiftRel R ca cb ↔ LiftRel R ca' cb' 
goal: Computation.LiftRel R ca cb ↔ Computation.LiftRel R ca' cb'

full_name: Computation.liftRel_map
code: theorem liftRel_map {δ} (R : α → β → Prop) (S : γ → δ → Prop) {s1 : Computation α}
    {s2 : Computation β} {f1 : α → γ} {f2 : β → δ} (h1 : LiftRel R s1 s2)
    (h2 : ∀ {a b}, R a b → S (f1 a) (f2 b)) : LiftRel S (map f1 s1) (map f2 s2) 
goal: Computation.LiftRel S (Computation.map f1 s1) (Computation.map f2 s2)

full_name: Computation.map_congr
code: theorem map_congr {s1 s2 : Computation α} {f : α → β}
    (h1 : s1 ~ s2) : map f s1 ~ map f s2 
goal: (Computation.map f s1).Equiv (Computation.map f s2)

full_name: Computation.LiftRelAux
code: /-- Alternate definition of `LiftRel` over relations between `Computation`s-/
def LiftRelAux (R : α → β → Prop) (C : Computation α → Computation β → Prop) :
    α ⊕ (Computation α) → β ⊕ (Computation β) → Prop
  
goal: α ⊕ Computation α → β ⊕ Computation β → Prop

full_name: Computation.liftRelAux_inl_inl
code: @[simp] lemma liftRelAux_inl_inl {a : α} {b : β} :
  LiftRelAux R C (Sum.inl a) (Sum.inl b) = R a b 
goal: Computation.LiftRelAux R C (Sum.inl a) (Sum.inl b) = R a b

full_name: Computation.liftRelAux_inl_inr
code: @[simp] lemma liftRelAux_inl_inr {a : α} {cb} :
    LiftRelAux R C (Sum.inl a) (Sum.inr cb) = ∃ b, b ∈ cb ∧ R a b 
goal: Computation.LiftRelAux R C (Sum.inl a) (Sum.inr cb) = ∃ b, b ∈ cb ∧ R a b

full_name: Computation.liftRelAux_inr_inl
code: @[simp] lemma liftRelAux_inr_inl {b : β} {ca} :
    LiftRelAux R C (Sum.inr ca) (Sum.inl b) = ∃ a, a ∈ ca ∧ R a b 
goal: Computation.LiftRelAux R C (Sum.inr ca) (Sum.inl b) = ∃ a, a ∈ ca ∧ R a b

full_name: Computation.liftRelAux_inr_inr
code: @[simp] lemma liftRelAux_inr_inr {ca cb} :
    LiftRelAux R C (Sum.inr ca) (Sum.inr cb) = C ca cb 
goal: Computation.LiftRelAux R C (Sum.inr ca) (Sum.inr cb) = C ca cb

full_name: Computation.LiftRelAux.ret_left
code: @[simp]
theorem LiftRelAux.ret_left (R : α → β → Prop) (C : Computation α → Computation β → Prop) (a cb) :
    LiftRelAux R C (Sum.inl a) (destruct cb) ↔ ∃ b, b ∈ cb ∧ R a b 
goal: Computation.LiftRelAux R C (Sum.inl a) cb.destruct ↔ ∃ b, b ∈ cb ∧ R a b

full_name: Computation.LiftRelAux.swap
code: theorem LiftRelAux.swap (R : α → β → Prop) (C) (a b) :
    LiftRelAux (swap R) (swap C) b a = LiftRelAux R C a b 
goal: Computation.LiftRelAux (Function.swap R) (Function.swap C) b a = Computation.LiftRelAux R C a b

full_name: Computation.LiftRelAux.ret_right
code: @[simp]
theorem LiftRelAux.ret_right (R : α → β → Prop) (C : Computation α → Computation β → Prop) (b ca) :
    LiftRelAux R C (destruct ca) (Sum.inl b) ↔ ∃ a, a ∈ ca ∧ R a b 
goal: Computation.LiftRelAux R C ca.destruct (Sum.inl b) ↔ ∃ a, a ∈ ca ∧ R a b

full_name: Computation.LiftRelRec.lem
code: theorem LiftRelRec.lem {R : α → β → Prop} (C : Computation α → Computation β → Prop)
    (H : ∀ {ca cb}, C ca cb → LiftRelAux R C (destruct ca) (destruct cb)) (ca cb) (Hc : C ca cb) (a)
    (ha : a ∈ ca) : LiftRel R ca cb 
goal: Computation.LiftRel R ca cb

full_name: Computation.liftRel_rec
code: theorem liftRel_rec {R : α → β → Prop} (C : Computation α → Computation β → Prop)
    (H : ∀ {ca cb}, C ca cb → LiftRelAux R C (destruct ca) (destruct cb)) (ca cb) (Hc : C ca cb) :
    LiftRel R ca cb 
goal: Computation.LiftRel R ca cb