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.
Equations
- computation α = {f // ∀ ⦃n : ℕ⦄ ⦃a : α⦄, f n = option.some a → f (n + 1) = option.some a}
return a is the computation that immediately terminates with result a.
Equations
- computation.return a = ⟨stream.const (option.some a), _⟩
Instances for computation.return
Equations
think c is the computation that delays for one "tick" and then performs
computation c.
Instances for computation.think
thinkN c n is the computation that delays for n ticks and then performs
computation c.
Instances for computation.thinkN
head c is the first step of computation, either some a if c = return a
or none if c = think c'.
tail c is the remainder of computation, either c if c = return a
or c' if c = think c'.
empty α is the computation that never returns, an infinite sequence of
thinks.
Equations
Equations
run_for c n evaluates c for n steps and returns the result, or none
if it did not terminate after n steps.
Equations
destruct c is the destructor for computation α as a coinductive type.
It returns inl a if c = return a and inr c' if c = think c'.
Equations
- c.destruct = computation.destruct._match_1 c (c.val 0)
- computation.destruct._match_1 c (option.some a) = sum.inl a
- computation.destruct._match_1 c option.none = sum.inr c.tail
Recursion principle for computations, compare with list.rec_on.
Equations
- s.rec_on h1 h2 = (λ (_x : α ⊕ computation α) (H : s.destruct = _x), sum.rec (λ (v : α) (H : s.destruct = sum.inl v), _.mpr (h1 v)) (λ (v : computation α) (H : s.destruct = sum.inr v), subtype.cases_on v (λ (a : stream (option α)) (s' : ∀ ⦃n : ℕ⦄ ⦃a_1 : α⦄, a n = option.some a_1 → a (n + 1) = option.some a_1) (H : s.destruct = sum.inr ⟨a, s'⟩), _.mpr (h2 ⟨a, s'⟩)) H) _x H) s.destruct _
Equations
- computation.corec.F f (sum.inr b) = (computation.corec.F._match_1 (f b), f b)
- computation.corec.F f (sum.inl a) = (option.some a, sum.inl a)
- computation.corec.F._match_1 (sum.inr b') = option.none
- computation.corec.F._match_1 (sum.inl a) = option.some a
corec f b is the corecursor for computation α as a coinductive type.
If f b = inl a then corec f b = return a, and if f b = inl b' then
corec f b = think (corec f b').
Equations
- computation.corec f b = ⟨stream.corec' (computation.corec.F f) (sum.inr b), _⟩
Equations
- computation.bisim_o R (sum.inr s) (sum.inr s') = R s s'
- computation.bisim_o R (sum.inr val) (sum.inl val_1) = false
- computation.bisim_o R (sum.inl val) (sum.inr val_1) = false
- computation.bisim_o R (sum.inl a) (sum.inl a') = (a = a')
Equations
- computation.is_bisimulation R = ∀ ⦃s₁ s₂ : computation α⦄, R s₁ s₂ → computation.bisim_o R s₁.destruct s₂.destruct
Equations
- computation.mem a s = (option.some a ∈ s.val)
Equations
terminates s asserts that the computation s eventually terminates with some value.
promises s a, or s ~> a, asserts that although the computation s
may not terminate, if it does, then the result is a.
length s gets the number of steps of a terminating computation
get s returns the result of a terminating computation
Equations
- s.get = option.get _
Equations
- computation.mem_rec_on M h1 h2 = _.mpr (_.mpr (nat.rec h1 (λ (n : ℕ) (IH : C ((computation.return a).thinkN n)), h2 ((computation.return a).thinkN n) IH) s.length))
Equations
- s.terminates_rec_on h1 h2 = computation.mem_rec_on _ (h1 s.get) h2
Map a function on the result of a computation.
Equations
- computation.map f ⟨s, al⟩ = ⟨stream.map (λ (o : option α), o.cases_on option.none (option.some ∘ f)) s, _⟩
Instances for computation.map
Equations
- computation.bind.G (sum.inr cb') = sum.inr (sum.inr cb')
- computation.bind.G (sum.inl b) = sum.inl b
Equations
- computation.bind.F f (sum.inr cb) = computation.bind.G cb.destruct
- computation.bind.F f (sum.inl ca) = computation.bind.F._match_1 f ca.destruct
- computation.bind.F._match_1 f (sum.inr ca') = sum.inr (sum.inl ca')
- computation.bind.F._match_1 f (sum.inl a) = computation.bind.G (f a).destruct
Compose two computations into a monadic bind operation.
Equations
- c.bind f = computation.corec (computation.bind.F f) (sum.inl c)
Instances for computation.bind
Equations
Flatten a computation of computations into a single computation.
Equations
c₁ <|> c₂ calculates c₁ and c₂ simultaneously, returning
the first one that gives a result.
Equations
- c₁.orelse c₂ = computation.corec (λ (_x : computation α × computation α), computation.orelse._match_3 _x) (c₁, c₂)
- computation.orelse._match_3 (c₁, c₂) = computation.orelse._match_1 c₂ c₁.destruct
- computation.orelse._match_1 c₂ (sum.inr c₁') = computation.orelse._match_2 c₁' c₂.destruct
- computation.orelse._match_1 c₂ (sum.inl a) = sum.inl a
- computation.orelse._match_2 c₁' (sum.inr c₂') = sum.inr (c₁', c₂')
- computation.orelse._match_2 c₁' (sum.inl a) = sum.inl a
Equations
c₁ ~ c₂ asserts that c₁ and c₂ either both terminate with the same result,
or both loop forever.
lift_rel 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.