Imports
/-
Copyright (c) 2026 Terence Rokop. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Terence Rokop
-/
module
public import Geb.Prototypes.Computability.CobhamFoldProto.BoundSelf-delimiting bitstrings in Cobham's class
A stack whose entries are bitstrings of varying length needs entries that delimit themselves, and a step that reads one needs to parse it. This module supplies the parsing primitives as expressions of Cobham's class.
An entry spelling the payload u is List.replicate u.length true followed by
false followed by u: a unary length prefix, read from the list's head, which
is the end a step of the outer scan pops from.
Cobham.scan lifts steps of arity one, applying them to the recursive value
alone. dropUnaryOf, dropEntryOf and takeEntryOf need the remaining word as
well,
which Cobham.evalRec supplies in slot zero of a step's environment, so scan2
takes its steps at arity two directly.
takeEntryOf is the one whose use of it is least avoidable. Its recursion
appends a bit at the end of the payload accumulated so far, which is not a
head operation; the concat generator supplies the append, and the appended bit is read
off the remaining word by firstBitOf after dropEntryOf. Without slot zero the
payload would not be extractable and the algebra could not be applied.
Main definitions
Geb.CobhamFold.scan2 — the arity-two scan node as an expression;
Geb.CobhamFold.scan2Raw itself lives with the scan combinators in
Geb/Prototypes/Computability/CobhamFoldProto/Bound.lean.
Geb.CobhamFold.entryWord — the self-delimiting spelling of a payload.
Geb.CobhamFold.firstBitOf, Geb.CobhamFold.unaryOf,
Geb.CobhamFold.takeUnaryOf, Geb.CobhamFold.dropUnaryOf,
Geb.CobhamFold.dropEntryOf, Geb.CobhamFold.takeEntryOf — the parsing
primitives.
Geb.CobhamFold.idOf, Geb.CobhamFold.dropEntriesOf,
Geb.CobhamFold.entryOf — the identity, and the primitives iterated to reach
the j-th entry. The composition combinators they are built from live in
Geb/Prototypes/Computability/CobhamFoldProto/Bound.lean.
Main statements
Geb.CobhamFold.scan2Sem_nil, Geb.CobhamFold.scan2Sem_cons — the arity-two
scan on the empty word and on one bit.
Geb.CobhamFold.stepWord_firstBitOf, Geb.CobhamFold.stepWord_unaryOf,
Geb.CobhamFold.stepWord_takeUnaryOf,
Geb.CobhamFold.stepWord_dropUnaryOf,
Geb.CobhamFold.stepWord_dropEntryOf,
Geb.CobhamFold.stepWord_takeEntryOf — what each primitive computes.
Geb.CobhamFold.take_succ_append_take_one — a truncation splits at its
last bit.
Geb.CobhamFold.takeEntrySem_entryWord,
Geb.CobhamFold.dropEntrySem_entryWord — the payload and the remainder of a
self-delimiting entry.
Geb.CobhamFold.two_mul_length_takeEntrySem_add_length_dropEntrySem_le —
the payload counted twice and the remainder fit inside the word.
Geb.CobhamFold.scan2Sem_eq_eval — the meaning read at the raw tree is the
meaning the expression carries.
Implementation notes
Every primitive's value is no longer than its argument, so each takes
Cobham.boundRaw 0 as its bound child: the recursion variable itself dominates.
The bounds are established over arbitrary words, not only over well-formed
entries, since Cobham.RecBoundedValue quantifies over every environment.
Each primitive recurses over the whole word, not over the entry it reads.
Cobham.evalRec recurses to the empty word whatever the value depends on, so
dropEntryOf touches every bit of its argument although, at an entry spelling
the payload u, the first 2 * u.length + 1 bits are what fix where its value
starts. Their steps are not constant either: dropEntryOf's
applies Cobham.pred, itself a boundedRec, and takeEntryOf's runs a fresh
dropEntryOf over the remaining word, so counting a boundedRec's cost as the
sum over its levels of its step's cost makes dropEntryOf quadratic in its
argument and takeEntryOf cubic.
Nothing here measures a number of reduction steps, as
Geb/Mathlib/Computability/Cobham/Tree.lean records of its own subject; the
paragraph above analyses the expression under one cost model.
The accompanying lower bound rests only on the class's shape rather than on a
cost model: reading an unbounded field of the state requires a recursion over
the state, boundedRec being the class's only recursion. It is an argument
about the expression, not a theorem stated here.
That gives a dichotomy rather than a spectrum, in what a step reads rather than
in what it costs. A carrier whose values are bounded by a constant is the
fixed-width case — pad to that constant and dispatch on a constant window, and
no step reads an unbounded field. A carrier whose values are unbounded needs
entries of this shape, and every step reads one. There is no intermediate
regime, a bound of any constant B being the fixed-width case at width B.
Neither case has constant-time steps: reading even a bounded prefix of the state
goes through a boundedRec over the state.
Only boundedRec nodes carry a Cobham.RecBoundedValue obligation, comp's
being vacuous, so composing these primitives imposes no further bound. This is
why entryWord's spelling, which is longer than its argument, needs no growth
allowance: it is a composition, not a recursion.
References
[Cobham1965]
Tags
Cobham, bounded recursion on notation, self-delimiting, prefix code
@[expose] public sectionnamespace Geb.CobhamFoldopen CobhamThe arity-two scan node over expressions, carrying its admissibility.
def scan2W (base : COf 0) (step₀ step₁ : COf 2) : sig.W :=
⟨scan2Raw base.1.1.1 step₀.1.1.1 step₁.1.1.1 (boundRaw 0),
wValid_scan2Raw _ _ _ _ base.1.1.2 base.2 step₀.1.1.2 step₀.2
step₁.1.1.2 step₁.2 (wValid_boundRaw 0) (wIndexRoot_boundRaw 0)⟩The arity-two scan node's arity.
theorem arity_scan2W (base : COf 0) (step₀ step₁ : COf 2) :
arity (scan2W base step₀ step₁) = 1 := rflThe meaning of the arity-two scan at its arity.
def scan2Sem (base : COf 0) (step₀ step₁ : COf 2) : Sem 1 :=
semAt 1 (scan2W base step₀ step₁) (arity_scan2W base step₀ step₁)The word an arity-two step contributes at the remaining word and the recursive value.
The arity-two scan on the empty bitstring is its base's word.
theorem scan2Sem_nil (base : COf 0) (step₀ step₁ : COf 2) :
scan2Sem base step₀ step₁ ![[]] = baseWord base := rflOne step of the arity-two scan, which reads the remaining word as well as the value the scan of that word returns.
theorem scan2Sem_cons (base : COf 0) (step₀ step₁ : COf 2) (b : Bool)
(w : List Bool) :
scan2Sem base step₀ step₁ ![b :: w] =
step2Word (if b then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w]) := base:COf 0step₀:COf 2step₁:COf 2b:Boolw:List Bool⊢ scan2Sem base step₀ step₁ ![b :: w] = step2Word (if b = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w])
base:COf 0step₀:COf 2step₁:COf 2b:Boolw:List Boolhfun:∀ (v r : List Bool), Fin.cons v (Fin.cons r Fin.elim0) = ![v, r]⊢ scan2Sem base step₀ step₁ ![b :: w] = step2Word (if b = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w])
base:COf 0step₀:COf 2step₁:COf 2w:List Boolhfun:∀ (v r : List Bool), Fin.cons v (Fin.cons r Fin.elim0) = ![v, r]⊢ scan2Sem base step₀ step₁ ![false :: w] =
step2Word (if false = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w])base:COf 0step₀:COf 2step₁:COf 2w:List Boolhfun:∀ (v r : List Bool), Fin.cons v (Fin.cons r Fin.elim0) = ![v, r]⊢ scan2Sem base step₀ step₁ ![true :: w] =
step2Word (if true = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w])
base:COf 0step₀:COf 2step₁:COf 2w:List Boolhfun:∀ (v r : List Bool), Fin.cons v (Fin.cons r Fin.elim0) = ![v, r]⊢ scan2Sem base step₀ step₁ ![false :: w] =
step2Word (if false = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w]) base:COf 0step₀:COf 2step₁:COf 2w:List Boolhfun:∀ (v r : List Bool), Fin.cons v (Fin.cons r Fin.elim0) = ![v, r]⊢ transport ⋯ (eval ↑↑step₀).snd (Fin.cons w (Fin.cons (scan2Sem base step₀ step₁ ![w]) Fin.elim0)) =
step2Word (if false = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w])
All goals completed! 🐙
base:COf 0step₀:COf 2step₁:COf 2w:List Boolhfun:∀ (v r : List Bool), Fin.cons v (Fin.cons r Fin.elim0) = ![v, r]⊢ scan2Sem base step₀ step₁ ![true :: w] =
step2Word (if true = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w]) base:COf 0step₀:COf 2step₁:COf 2w:List Boolhfun:∀ (v r : List Bool), Fin.cons v (Fin.cons r Fin.elim0) = ![v, r]⊢ transport ⋯ (eval ↑↑step₁).snd (Fin.cons w (Fin.cons (scan2Sem base step₀ step₁ ![w]) Fin.elim0)) =
step2Word (if true = true then step₁ else step₀) w (scan2Sem base step₀ step₁ ![w])
All goals completed! 🐙The arity-two scan as an expression of the class, its recursion bounded by the recursion variable itself.
def scan2 (base : COf 0) (step₀ step₁ : COf 2)
(hbound : ∀ w : List Bool, (scan2Sem base step₀ step₁ ![w]).length ≤ w.length) :
C :=
⟨scan2W base step₀ step₁, base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.length⊢ RecBounded (scan2W base step₀ step₁)
base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthx:Fin (0 + 1) → List Bool⊢ (evalRec
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
0)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
1)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
2)).snd)
(x 0) (Fin.tail x)).length ≤
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
3)).snd
x).lengthbase:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.length⊢ ∀
(b :
sig.B (↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).fst),
(fun b ↦
(fun a ↦
WType.rec (motive := fun w ↦ sig.WValid w → Prop)
(fun a f ih hv ↦
(fun x ih ↦ RecBoundedValue (↑x).fst (↑x).snd ⋯ ∧ ∀ (b : sig.B (↑x).fst), ih b)
(SlicePFunctor.W.dest ⟨WType.mk a f, hv⟩) fun b ↦ ih b ⋯)
(![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0] a))
b ⋯)
b
base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthx:Fin (0 + 1) → List Bool⊢ (evalRec
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
0)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
1)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
2)).snd)
(x 0) (Fin.tail x)).length ≤
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
3)).snd
x).length refine_1 base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthx:Fin (0 + 1) → List Bool⊢ (evalRec
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
0)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
1)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
2)).snd)
(x 0) (Fin.tail ![x 0])).length ≤
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
3)).snd
x).length
change _ ≤ (boundSem 0 x).length refine_1 base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthx:Fin (0 + 1) → List Bool⊢ (evalRec
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
0)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
1)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
2)).snd)
(x 0) (Fin.tail ![x 0])).length ≤
(boundSem 0 x).length
rw [boundSem_eq refine_1 base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthx:Fin (0 + 1) → List Bool⊢ (evalRec
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
0)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
1)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
2)).snd)
(x 0) (Fin.tail ![x 0])).length ≤
(List.replicate 0 true ++ x 0).length] refine_1 base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthx:Fin (0 + 1) → List Bool⊢ (evalRec
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
0)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
1)).snd)
(transport ⋯
(eval
((↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).snd
2)).snd)
(x 0) (Fin.tail ![x 0])).length ≤
(List.replicate 0 true ++ x 0).length
exact hbound (x 0) All goals completed! 🐙
· refine_2 base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.length⊢ ∀
(b :
sig.B (↑(SlicePFunctor.W.dest ⟨WType.mk (Shape.boundedRec 0) ![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0], ⋯⟩)).fst),
(fun b ↦
(fun a ↦
WType.rec (motive := fun w ↦ sig.WValid w → Prop)
(fun a f ih hv ↦
(fun x ih ↦ RecBoundedValue (↑x).fst (↑x).snd ⋯ ∧ ∀ (b : sig.B (↑x).fst), ih b)
(SlicePFunctor.W.dest ⟨WType.mk a f, hv⟩) fun b ↦ ih b ⋯)
(![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0] a))
b ⋯)
b refine fun b : Fin 4 ↦ ?_ refine_2 base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthb:Fin 4⊢ (fun b ↦
(fun a ↦
WType.rec (motive := fun w ↦ sig.WValid w → Prop)
(fun a f ih hv ↦
(fun x ih ↦ RecBoundedValue (↑x).fst (↑x).snd ⋯ ∧ ∀ (b : sig.B (↑x).fst), ih b)
(SlicePFunctor.W.dest ⟨WType.mk a f, hv⟩) fun b ↦ ih b ⋯)
(![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0] a))
b ⋯)
b
match b with
| 0 => base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthb:Fin 4⊢ (fun b ↦
(fun a ↦
WType.rec (motive := fun w ↦ sig.WValid w → Prop)
(fun a f ih hv ↦
(fun x ih ↦ RecBoundedValue (↑x).fst (↑x).snd ⋯ ∧ ∀ (b : sig.B (↑x).fst), ih b)
(SlicePFunctor.W.dest ⟨WType.mk a f, hv⟩) fun b ↦ ih b ⋯)
(![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0] a))
b ⋯)
0 exact base.1.2 All goals completed! 🐙
| 1 => base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthb:Fin 4⊢ (fun b ↦
(fun a ↦
WType.rec (motive := fun w ↦ sig.WValid w → Prop)
(fun a f ih hv ↦
(fun x ih ↦ RecBoundedValue (↑x).fst (↑x).snd ⋯ ∧ ∀ (b : sig.B (↑x).fst), ih b)
(SlicePFunctor.W.dest ⟨WType.mk a f, hv⟩) fun b ↦ ih b ⋯)
(![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0] a))
b ⋯)
1 exact step₀.1.2 All goals completed! 🐙
| 2 => base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthb:Fin 4⊢ (fun b ↦
(fun a ↦
WType.rec (motive := fun w ↦ sig.WValid w → Prop)
(fun a f ih hv ↦
(fun x ih ↦ RecBoundedValue (↑x).fst (↑x).snd ⋯ ∧ ∀ (b : sig.B (↑x).fst), ih b)
(SlicePFunctor.W.dest ⟨WType.mk a f, hv⟩) fun b ↦ ih b ⋯)
(![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0] a))
b ⋯)
2 exact step₁.1.2 All goals completed! 🐙
| 3 => base:COf 0step₀:COf 2step₁:COf 2hbound:∀ (w : List Bool), (scan2Sem base step₀ step₁ ![w]).length ≤ w.lengthb:Fin 4⊢ (fun b ↦
(fun a ↦
WType.rec (motive := fun w ↦ sig.WValid w → Prop)
(fun a f ih hv ↦
(fun x ih ↦ RecBoundedValue (↑x).fst (↑x).snd ⋯ ∧ ∀ (b : sig.B (↑x).fst), ih b)
(SlicePFunctor.W.dest ⟨WType.mk a f, hv⟩) fun b ↦ ih b ⋯)
(![↑↑↑base, ↑↑↑step₀, ↑↑↑step₁, boundRaw 0] a))
b ⋯)
3 exact recBounded_boundRaw 0 All goals completed! 🐙⟩
scan2 at its declared arity.
def scan2Of (base : COf 0) (step₀ step₁ : COf 2)
(hbound : ∀ w : List Bool, (scan2Sem base step₀ step₁ ![w]).length ≤ w.length) :
COf 1 :=
⟨scan2 base step₀ step₁ hbound, rfl⟩The meaning read at the raw tree is the meaning the expression carries.
theorem scan2Sem_eq_eval (base : COf 0) (step₀ step₁ : COf 2)
(hbound : ∀ w : List Bool, (scan2Sem base step₀ step₁ ![w]).length ≤ w.length) :
transport (scan2Of base step₀ step₁ hbound).2
(scan2Of base step₀ step₁ hbound).1.eval =
scan2Sem base step₀ step₁ := rflPrepending a word prepends it to what an arity-two step contributes.
theorem step2Word_prependOf (e : COf 2) (v r : List Bool) :
∀ u : List Bool, step2Word (prependOf u e) v r = u ++ step2Word e v r :=
semAt_prependOf e ![v, r]A constant arity-two step contributes its word, whatever it reads.
theorem step2Word_constAtOf (u v r : List Bool) :
step2Word (constAtOf 2 u) v r = u :=
(step2Word_prependOf (zeroAtOf 2) v r u).trans (List.append_nil u)A projection contributes the slot it names.
theorem step2Word_projOf (i : Fin 2) (v r : List Bool) :
step2Word (projOf 2 i) v r = ![v, r] i := semAt_projOf 2 i ![v, r]A composition contributes its head's value at its argument's.
theorem step2Word_comp1Of (e : COf 1) (a : COf 2) (v r : List Bool) :
step2Word (comp1Of e a) v r = stepWord e (step2Word a v r) :=
congrArg (semAt 1 e.1.1 e.2) (funext fun i ↦ match i with | ⟨0, _⟩ => rfl)A concatenation contributes its second argument's value followed by its first's.
theorem step2Word_concatCompOf (a b : COf 2) (v r : List Bool) :
step2Word (concatCompOf 2 a b) v r =
step2Word b v r ++ step2Word a v r :=
semAt_concatCompOf 2 a b ![v, r]The predecessor's value at an arity-one step.
theorem stepWord_pred (u : List Bool) : stepWord pred u = u.tail :=
(stepWord_eq_eval pred u).trans (predSem_eq u)The first bit of a word, absent at the empty word.
What the first-bit primitive computes.
theorem firstBitSem_eq : ∀ w : List Bool,
firstBitSem ![w] = match w with | [] => [] | b :: _ => [b]
| [] => rfl
| b :: v => b:Boolv:List Bool⊢ firstBitSem ![b :: v] =
match b :: v with
| [] => []
| b :: tail => [b] by b:Boolv:List Bool⊢ firstBitSem ![b :: v] =
match b :: v with
| [] => []
| b :: tail => [b]
change scan2Sem _ _ _ ![b :: v] = _ b:Boolv:List Bool⊢ scan2Sem (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true]) ![b :: v] =
match b :: v with
| [] => []
| b :: tail => [b]
rw [scan2Sem_cons b:Boolv:List Bool⊢ step2Word (if b = true then constAtOf 2 [true] else constAtOf 2 [false]) v
(scan2Sem (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true]) ![v]) =
match b :: v with
| [] => []
| b :: tail => [b]] b:Boolv:List Bool⊢ step2Word (if b = true then constAtOf 2 [true] else constAtOf 2 [false]) v
(scan2Sem (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true]) ![v]) =
match b :: v with
| [] => []
| b :: tail => [b]
cases b false v:List Bool⊢ step2Word (if false = true then constAtOf 2 [true] else constAtOf 2 [false]) v
(scan2Sem (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true]) ![v]) =
match false :: v with
| [] => []
| b :: tail => [b]true v:List Bool⊢ step2Word (if true = true then constAtOf 2 [true] else constAtOf 2 [false]) v
(scan2Sem (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true]) ![v]) =
match true :: v with
| [] => []
| b :: tail => [b] <;> false v:List Bool⊢ step2Word (if false = true then constAtOf 2 [true] else constAtOf 2 [false]) v
(scan2Sem (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true]) ![v]) =
match false :: v with
| [] => []
| b :: tail => [b]true v:List Bool⊢ step2Word (if true = true then constAtOf 2 [true] else constAtOf 2 [false]) v
(scan2Sem (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true]) ![v]) =
match true :: v with
| [] => []
| b :: tail => [b] exact step2Word_constAtOf _ _ _ All goals completed! 🐙The first-bit primitive never lengthens its argument.
theorem length_firstBitSem_le (w : List Bool) : (firstBitSem ![w]).length ≤ w.length := by w:List Bool⊢ (firstBitSem ![w]).length ≤ w.length
rw [firstBitSem_eq w:List Bool⊢ (match w with
| [] => []
| b :: tail => [b]).length ≤
w.length] w:List Bool⊢ (match w with
| [] => []
| b :: tail => [b]).length ≤
w.length
match w with
| [] => w:List Bool⊢ (match [] with
| [] => []
| b :: tail => [b]).length ≤
[].length exact Nat.le_refl 0 All goals completed! 🐙
| _ :: _ => w:List Boolhead✝:Booltail✝:List Bool⊢ (match head✝ :: tail✝ with
| [] => []
| b :: tail => [b]).length ≤
(head✝ :: tail✝).length
rw [List.length_cons, w:List Boolhead✝:Booltail✝:List Bool⊢ [].length + 1 ≤ (head✝ :: tail✝).length List.length_cons, w:List Boolhead✝:Booltail✝:List Bool⊢ [].length + 1 ≤ tail✝.length + 1 List.length_nil w:List Boolhead✝:Booltail✝:List Bool⊢ 0 + 1 ≤ tail✝.length + 1] w:List Boolhead✝:Booltail✝:List Bool⊢ 0 + 1 ≤ tail✝.length + 1
omega All goals completed! 🐙The first bit of a word as an expression of arity one.
def firstBitOf : COf 1 :=
scan2Of (zeroAtOf 0) (constAtOf 2 [false]) (constAtOf 2 [true])
length_firstBitSem_leThe first-bit expression's value at a step.
@[simp] theorem stepWord_firstBitOf (w : List Bool) :
stepWord firstBitOf w = firstBitSem ![w] := rflA word's length in unary.
def unarySem : Sem 1 :=
scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1))
(prependOf [true] (projOf 2 1))
One step of the unary primitive: each bit read contributes a true.
theorem unarySem_cons (b : Bool) (v : List Bool) :
unarySem ![b :: v] = true :: unarySem ![v] := by b:Boolv:List Bool⊢ unarySem ![b :: v] = true :: unarySem ![v]
change scan2Sem _ _ _ ![b :: v] = _ b:Boolv:List Bool⊢ scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1)) (prependOf [true] (projOf 2 1)) ![b :: v] = true :: unarySem ![v]
rw [scan2Sem_cons b:Boolv:List Bool⊢ step2Word (if b = true then prependOf [true] (projOf 2 1) else prependOf [true] (projOf 2 1)) v
(scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1)) (prependOf [true] (projOf 2 1)) ![v]) =
true :: unarySem ![v]] b:Boolv:List Bool⊢ step2Word (if b = true then prependOf [true] (projOf 2 1) else prependOf [true] (projOf 2 1)) v
(scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1)) (prependOf [true] (projOf 2 1)) ![v]) =
true :: unarySem ![v]
cases b false v:List Bool⊢ step2Word (if false = true then prependOf [true] (projOf 2 1) else prependOf [true] (projOf 2 1)) v
(scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1)) (prependOf [true] (projOf 2 1)) ![v]) =
true :: unarySem ![v]true v:List Bool⊢ step2Word (if true = true then prependOf [true] (projOf 2 1) else prependOf [true] (projOf 2 1)) v
(scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1)) (prependOf [true] (projOf 2 1)) ![v]) =
true :: unarySem ![v] <;> false v:List Bool⊢ step2Word (if false = true then prependOf [true] (projOf 2 1) else prependOf [true] (projOf 2 1)) v
(scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1)) (prependOf [true] (projOf 2 1)) ![v]) =
true :: unarySem ![v]true v:List Bool⊢ step2Word (if true = true then prependOf [true] (projOf 2 1) else prependOf [true] (projOf 2 1)) v
(scan2Sem (zeroAtOf 0) (prependOf [true] (projOf 2 1)) (prependOf [true] (projOf 2 1)) ![v]) =
true :: unarySem ![v]
exact (step2Word_prependOf (projOf 2 1) v _ [true]).trans
(congrArg (fun t ↦ true :: t) (step2Word_projOf 1 v _)) All goals completed! 🐙The unary primitive spells its argument's length.
theorem unarySem_eq : ∀ w : List Bool,
unarySem ![w] = List.replicate w.length true :=
List.rec rfl fun b v ih ↦ by b:Boolv:List Boolih:unarySem ![v] = List.replicate v.length true⊢ unarySem ![b :: v] = List.replicate (b :: v).length true
rw [unarySem_cons, b:Boolv:List Boolih:unarySem ![v] = List.replicate v.length true⊢ true :: unarySem ![v] = List.replicate (b :: v).length true ih, b:Boolv:List Boolih:unarySem ![v] = List.replicate v.length true⊢ true :: List.replicate v.length true = List.replicate (b :: v).length true List.length_cons, b:Boolv:List Boolih:unarySem ![v] = List.replicate v.length true⊢ true :: List.replicate v.length true = List.replicate (v.length + 1) true List.replicate_succ b:Boolv:List Boolih:unarySem ![v] = List.replicate v.length true⊢ true :: List.replicate v.length true = true :: List.replicate v.length true] All goals completed! 🐙The unary primitive never lengthens its argument.
theorem length_unarySem_le (w : List Bool) : (unarySem ![w]).length ≤ w.length := by w:List Bool⊢ (unarySem ![w]).length ≤ w.length
rw [unarySem_eq, w:List Bool⊢ (List.replicate w.length true).length ≤ w.length List.length_replicate w:List Bool⊢ w.length ≤ w.length] All goals completed! 🐙A word's length in unary, as an expression of arity one.
def unaryOf : COf 1 :=
scan2Of (zeroAtOf 0) (prependOf [true] (projOf 2 1))
(prependOf [true] (projOf 2 1)) length_unarySem_leThe unary expression's value at a step.
The word past a unary length prefix and its sentinel.
The prefix-dropping primitive on the empty word.
theorem dropUnarySem_nil : dropUnarySem ![[]] = [] := rfl
What the prefix-dropping primitive computes: a true keeps the recursive
value, a false ends the prefix and returns the remaining word.
theorem dropUnarySem_cons (b : Bool) (v : List Bool) :
dropUnarySem ![b :: v] = if b then dropUnarySem ![v] else v := by b:Boolv:List Bool⊢ dropUnarySem ![b :: v] = if b = true then dropUnarySem ![v] else v
change scan2Sem _ _ _ ![b :: v] = _ b:Boolv:List Bool⊢ scan2Sem (zeroAtOf 0) (projOf 2 0) (projOf 2 1) ![b :: v] = if b = true then dropUnarySem ![v] else v
rw [scan2Sem_cons b:Boolv:List Bool⊢ step2Word (if b = true then projOf 2 1 else projOf 2 0) v (scan2Sem (zeroAtOf 0) (projOf 2 0) (projOf 2 1) ![v]) =
if b = true then dropUnarySem ![v] else v] b:Boolv:List Bool⊢ step2Word (if b = true then projOf 2 1 else projOf 2 0) v (scan2Sem (zeroAtOf 0) (projOf 2 0) (projOf 2 1) ![v]) =
if b = true then dropUnarySem ![v] else v
cases b false v:List Bool⊢ step2Word (if false = true then projOf 2 1 else projOf 2 0) v (scan2Sem (zeroAtOf 0) (projOf 2 0) (projOf 2 1) ![v]) =
if false = true then dropUnarySem ![v] else vtrue v:List Bool⊢ step2Word (if true = true then projOf 2 1 else projOf 2 0) v (scan2Sem (zeroAtOf 0) (projOf 2 0) (projOf 2 1) ![v]) =
if true = true then dropUnarySem ![v] else v
· false v:List Bool⊢ step2Word (if false = true then projOf 2 1 else projOf 2 0) v (scan2Sem (zeroAtOf 0) (projOf 2 0) (projOf 2 1) ![v]) =
if false = true then dropUnarySem ![v] else v exact step2Word_projOf 0 v _ All goals completed! 🐙
· true v:List Bool⊢ step2Word (if true = true then projOf 2 1 else projOf 2 0) v (scan2Sem (zeroAtOf 0) (projOf 2 0) (projOf 2 1) ![v]) =
if true = true then dropUnarySem ![v] else v exact step2Word_projOf 1 v _ All goals completed! 🐙The prefix-dropping primitive never lengthens its argument.
theorem length_dropUnarySem_le : ∀ w : List Bool,
(dropUnarySem ![w]).length ≤ w.length :=
List.rec (Nat.le_refl 0) fun b v ih ↦ by b:Boolv:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (dropUnarySem ![b :: v]).length ≤ (b :: v).length
rw [dropUnarySem_cons, b:Boolv:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (if b = true then dropUnarySem ![v] else v).length ≤ (b :: v).length List.length_cons b:Boolv:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (if b = true then dropUnarySem ![v] else v).length ≤ v.length + 1] b:Boolv:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (if b = true then dropUnarySem ![v] else v).length ≤ v.length + 1
cases b false v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (if false = true then dropUnarySem ![v] else v).length ≤ v.length + 1true v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (if true = true then dropUnarySem ![v] else v).length ≤ v.length + 1
· false v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (if false = true then dropUnarySem ![v] else v).length ≤ v.length + 1 rw [ite_eq_right (by v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ ¬false = true simp All goals completed! 🐙)] false v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ v.length ≤ v.length + 1
omega All goals completed! 🐙
· true v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (if true = true then dropUnarySem ![v] else v).length ≤ v.length + 1 rw [ite_eq_left rfl true v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (dropUnarySem ![v]).length ≤ v.length + 1] true v:List Boolih:(dropUnarySem ![v]).length ≤ v.length⊢ (dropUnarySem ![v]).length ≤ v.length + 1
omega All goals completed! 🐙The word past a unary length prefix, as an expression of arity one.
The prefix-dropping expression's value at a step.
@[simp] theorem stepWord_dropUnaryOf (w : List Bool) :
stepWord dropUnaryOf w = dropUnarySem ![w] := rflThe word past a whole self-delimiting entry.
The entry-dropping primitive on the empty word.
theorem dropEntrySem_nil : dropEntrySem ![[]] = [] := rfl
What the entry-dropping primitive computes: a true lengthens the prefix by
one and so drops one more payload bit, and a false ends the prefix.
theorem dropEntrySem_cons (b : Bool) (v : List Bool) :
dropEntrySem ![b :: v] = if b then (dropEntrySem ![v]).tail else v := by b:Boolv:List Bool⊢ dropEntrySem ![b :: v] = if b = true then (dropEntrySem ![v]).tail else v
change scan2Sem _ _ _ ![b :: v] = _ b:Boolv:List Bool⊢ scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![b :: v] =
if b = true then (dropEntrySem ![v]).tail else v
rw [scan2Sem_cons b:Boolv:List Bool⊢ step2Word (if b = true then comp1Of pred (projOf 2 1) else projOf 2 0) v
(scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]) =
if b = true then (dropEntrySem ![v]).tail else v] b:Boolv:List Bool⊢ step2Word (if b = true then comp1Of pred (projOf 2 1) else projOf 2 0) v
(scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]) =
if b = true then (dropEntrySem ![v]).tail else v
cases b false v:List Bool⊢ step2Word (if false = true then comp1Of pred (projOf 2 1) else projOf 2 0) v
(scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]) =
if false = true then (dropEntrySem ![v]).tail else vtrue v:List Bool⊢ step2Word (if true = true then comp1Of pred (projOf 2 1) else projOf 2 0) v
(scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]) =
if true = true then (dropEntrySem ![v]).tail else v
· false v:List Bool⊢ step2Word (if false = true then comp1Of pred (projOf 2 1) else projOf 2 0) v
(scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]) =
if false = true then (dropEntrySem ![v]).tail else v exact step2Word_projOf 0 v _ All goals completed! 🐙
· true v:List Bool⊢ step2Word (if true = true then comp1Of pred (projOf 2 1) else projOf 2 0) v
(scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]) =
if true = true then (dropEntrySem ![v]).tail else v refine (step2Word_comp1Of pred (projOf 2 1) v _).trans ?_ true v:List Bool⊢ stepWord pred (step2Word (projOf 2 1) v (scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v])) =
if true = true then (dropEntrySem ![v]).tail else v
rw [step2Word_projOf true v:List Bool⊢ stepWord pred (![v, scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]] 1) =
if true = true then (dropEntrySem ![v]).tail else v] true v:List Bool⊢ stepWord pred (![v, scan2Sem (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1)) ![v]] 1) =
if true = true then (dropEntrySem ![v]).tail else v
exact stepWord_pred _ All goals completed! 🐙The entry-dropping primitive never lengthens its argument.
theorem length_dropEntrySem_le : ∀ w : List Bool,
(dropEntrySem ![w]).length ≤ w.length :=
List.rec (Nat.le_refl 0) fun b v ih ↦ by b:Boolv:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (dropEntrySem ![b :: v]).length ≤ (b :: v).length
rw [dropEntrySem_cons, b:Boolv:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (if b = true then (dropEntrySem ![v]).tail else v).length ≤ (b :: v).length List.length_cons b:Boolv:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (if b = true then (dropEntrySem ![v]).tail else v).length ≤ v.length + 1] b:Boolv:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (if b = true then (dropEntrySem ![v]).tail else v).length ≤ v.length + 1
cases b false v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (if false = true then (dropEntrySem ![v]).tail else v).length ≤ v.length + 1true v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (if true = true then (dropEntrySem ![v]).tail else v).length ≤ v.length + 1
· false v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (if false = true then (dropEntrySem ![v]).tail else v).length ≤ v.length + 1 rw [ite_eq_right (by v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ ¬false = true simp All goals completed! 🐙)] false v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ v.length ≤ v.length + 1
omega All goals completed! 🐙
· true v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (if true = true then (dropEntrySem ![v]).tail else v).length ≤ v.length + 1 rw [ite_eq_left rfl, true v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (dropEntrySem ![v]).tail.length ≤ v.length + 1 List.length_tail true v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (dropEntrySem ![v]).length - 1 ≤ v.length + 1] true v:List Boolih:(dropEntrySem ![v]).length ≤ v.length⊢ (dropEntrySem ![v]).length - 1 ≤ v.length + 1
omega All goals completed! 🐙The word past a whole self-delimiting entry, as an expression of arity one.
def dropEntryOf : COf 1 :=
scan2Of (zeroAtOf 0) (projOf 2 0) (comp1Of pred (projOf 2 1))
length_dropEntrySem_leThe entry-dropping expression's value at a step.
@[simp] theorem stepWord_dropEntryOf (w : List Bool) :
stepWord dropEntryOf w = dropEntrySem ![w] := rflThe payload of a self-delimiting entry.
def takeEntrySem : Sem 1 :=
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0)))
(projOf 2 1))The payload primitive on the empty word.
theorem takeEntrySem_nil : takeEntrySem ![[]] = [] := rfl
What the payload primitive computes. The true clause appends one bit at
the payload's end, which the concat generator supplies and which is read off the
remaining word rather than off the recursive value.
theorem takeEntrySem_cons (b : Bool) (v : List Bool) :
takeEntrySem ![b :: v] =
if b then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else [] := by b:Boolv:List Bool⊢ takeEntrySem ![b :: v] = if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []
change scan2Sem _ _ _ ![b :: v] = _ b:Boolv:List Bool⊢ scan2Sem (zeroAtOf 0) (zeroAtOf 2) (concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1))
![b :: v] =
if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []
rw [scan2Sem_cons b:Boolv:List Bool⊢ step2Word
(if b = true then concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)
else zeroAtOf 2)
v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []] b:Boolv:List Bool⊢ step2Word
(if b = true then concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)
else zeroAtOf 2)
v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []
cases b false v:List Bool⊢ step2Word
(if false = true then concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)
else zeroAtOf 2)
v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if false = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []true v:List Bool⊢ step2Word
(if true = true then concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)
else zeroAtOf 2)
v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []
· false v:List Bool⊢ step2Word
(if false = true then concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)
else zeroAtOf 2)
v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if false = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else [] exact step2Word_constAtOf [] v _ All goals completed! 🐙
· true v:List Bool⊢ step2Word
(if true = true then concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)
else zeroAtOf 2)
v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else [] refine (step2Word_concatCompOf _ _ v _).trans ?_ true v:List Bool⊢ step2Word (projOf 2 1) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) ++
step2Word (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []
rw [step2Word_projOf, true v:List Bool⊢ ![v,
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]]
1 ++
step2Word (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else [] step2Word_comp1Of, true v:List Bool⊢ ![v,
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]]
1 ++
stepWord firstBitOf
(step2Word (comp1Of dropEntryOf (projOf 2 0)) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v])) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else [] step2Word_comp1Of, true v:List Bool⊢ ![v,
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]]
1 ++
stepWord firstBitOf
(stepWord dropEntryOf
(step2Word (projOf 2 0) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]))) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []
step2Word_projOf true v:List Bool⊢ ![v,
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]]
1 ++
stepWord firstBitOf
(stepWord dropEntryOf
(![v,
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]]
0)) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []] true v:List Bool⊢ ![v,
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]]
1 ++
stepWord firstBitOf
(stepWord dropEntryOf
(![v,
scan2Sem (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0))) (projOf 2 1)) ![v]]
0)) =
if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []
rfl All goals completed! 🐙The payload primitive never lengthens its argument.
theorem length_takeEntrySem_le : ∀ w : List Bool,
(takeEntrySem ![w]).length ≤ w.length :=
List.rec (Nat.le_refl 0) fun b v ih ↦ by b:Boolv:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (takeEntrySem ![b :: v]).length ≤ (b :: v).length
rw [takeEntrySem_cons, b:Boolv:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length ≤ (b :: v).length List.length_cons b:Boolv:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length ≤ v.length + 1] b:Boolv:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length ≤ v.length + 1
cases b false v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (if false = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length ≤ v.length + 1true v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length ≤ v.length + 1
· false v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (if false = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length ≤ v.length + 1 rw [ite_eq_right (by v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ ¬false = true simp All goals completed! 🐙), List.length_nil false v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ 0 ≤ v.length + 1] false v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ 0 ≤ v.length + 1
omega All goals completed! 🐙
· true v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length ≤ v.length + 1 rw [ite_eq_left rfl, true v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]]).length ≤ v.length + 1 List.length_append true v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (takeEntrySem ![v]).length + (firstBitSem ![dropEntrySem ![v]]).length ≤ v.length + 1] true v:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (takeEntrySem ![v]).length + (firstBitSem ![dropEntrySem ![v]]).length ≤ v.length + 1
have := length_firstBitSem_le (dropEntrySem ![v]) true v:List Boolih:(takeEntrySem ![v]).length ≤ v.lengththis:(firstBitSem ![dropEntrySem ![v]]).length ≤ (dropEntrySem ![v]).length⊢ (takeEntrySem ![v]).length + (firstBitSem ![dropEntrySem ![v]]).length ≤ v.length + 1
have := length_dropEntrySem_le v true v:List Boolih:(takeEntrySem ![v]).length ≤ v.lengththis✝:(firstBitSem ![dropEntrySem ![v]]).length ≤ (dropEntrySem ![v]).lengththis:(dropEntrySem ![v]).length ≤ v.length⊢ (takeEntrySem ![v]).length + (firstBitSem ![dropEntrySem ![v]]).length ≤ v.length + 1
have hfb : (firstBitSem ![dropEntrySem ![v]]).length ≤ 1 := by b:Boolv:List Boolih:(takeEntrySem ![v]).length ≤ v.length⊢ (takeEntrySem ![b :: v]).length ≤ (b :: v).length
rw [firstBitSem_eq v:List Boolih:(takeEntrySem ![v]).length ≤ v.lengththis✝:(firstBitSem ![dropEntrySem ![v]]).length ≤ (dropEntrySem ![v]).lengththis:(dropEntrySem ![v]).length ≤ v.length⊢ (match dropEntrySem ![v] with
| [] => []
| b :: tail => [b]).length ≤
1] v:List Boolih:(takeEntrySem ![v]).length ≤ v.lengththis✝:(firstBitSem ![dropEntrySem ![v]]).length ≤ (dropEntrySem ![v]).lengththis:(dropEntrySem ![v]).length ≤ v.length⊢ (match dropEntrySem ![v] with
| [] => []
| b :: tail => [b]).length ≤
1
match dropEntrySem ![v] with
| [] => v:List Boolih:(takeEntrySem ![v]).length ≤ v.lengththis✝:(firstBitSem ![dropEntrySem ![v]]).length ≤ (dropEntrySem ![v]).lengththis:(dropEntrySem ![v]).length ≤ v.length⊢ (match [] with
| [] => []
| b :: tail => [b]).length ≤
1 exact Nat.zero_le 1 All goals completed! 🐙
| _ :: _ => v:List Boolih:(takeEntrySem ![v]).length ≤ v.lengththis✝:(firstBitSem ![dropEntrySem ![v]]).length ≤ (dropEntrySem ![v]).lengththis:(dropEntrySem ![v]).length ≤ v.lengthhead✝:Booltail✝:List Bool⊢ (match head✝ :: tail✝ with
| [] => []
| b :: tail => [b]).length ≤
1 exact Nat.le_refl 1 true v:List Boolih:(takeEntrySem ![v]).length ≤ v.lengththis✝:(firstBitSem ![dropEntrySem ![v]]).length ≤ (dropEntrySem ![v]).lengththis:(dropEntrySem ![v]).length ≤ v.lengthhfb:(firstBitSem ![dropEntrySem ![v]]).length ≤ 1⊢ (takeEntrySem ![v]).length + (firstBitSem ![dropEntrySem ![v]]).length ≤ v.length + 1
omega All goals completed! 🐙
The payload and the remainder together fit inside the word, the payload
counted twice: a true lengthens the payload by at most one bit while the
remainder loses one, so the weighted total does not grow. This is what bounds
a general paramorphism step's contribution.
theorem two_mul_length_takeEntrySem_add_length_dropEntrySem_le :
∀ w : List Bool,
2 * (takeEntrySem ![w]).length + (dropEntrySem ![w]).length ≤ w.length :=
List.rec (Nat.le_refl 0) fun b v ih ↦ by b:Boolv:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (takeEntrySem ![b :: v]).length + (dropEntrySem ![b :: v]).length ≤ (b :: v).length
rw [takeEntrySem_cons, b:Boolv:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(dropEntrySem ![b :: v]).length ≤
(b :: v).length dropEntrySem_cons, b:Boolv:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(if b = true then (dropEntrySem ![v]).tail else v).length ≤
(b :: v).length List.length_cons b:Boolv:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(if b = true then (dropEntrySem ![v]).tail else v).length ≤
v.length + 1] b:Boolv:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if b = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(if b = true then (dropEntrySem ![v]).tail else v).length ≤
v.length + 1
cases b false v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if false = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(if false = true then (dropEntrySem ![v]).tail else v).length ≤
v.length + 1true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(if true = true then (dropEntrySem ![v]).tail else v).length ≤
v.length + 1
· false v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if false = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(if false = true then (dropEntrySem ![v]).tail else v).length ≤
v.length + 1 rw [ite_eq_right (by v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ ¬false = true simp All goals completed! 🐙), ite_eq_right (by v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ ¬false = true simp All goals completed! 🐙), List.length_nil false v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * 0 + v.length ≤ v.length + 1] false v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * 0 + v.length ≤ v.length + 1
omega All goals completed! 🐙
· true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (if true = true then takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]] else []).length +
(if true = true then (dropEntrySem ![v]).tail else v).length ≤
v.length + 1 rw [ite_eq_left rfl, true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]]).length +
(if true = true then (dropEntrySem ![v]).tail else v).length ≤
v.length + 1 ite_eq_left rfl, true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * (takeEntrySem ![v] ++ firstBitSem ![dropEntrySem ![v]]).length + (dropEntrySem ![v]).tail.length ≤ v.length + 1 List.length_append, true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * ((takeEntrySem ![v]).length + (firstBitSem ![dropEntrySem ![v]]).length) + (dropEntrySem ![v]).tail.length ≤
v.length + 1 List.length_tail, true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 * ((takeEntrySem ![v]).length + (firstBitSem ![dropEntrySem ![v]]).length) + ((dropEntrySem ![v]).length - 1) ≤
v.length + 1
firstBitSem_eq true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 *
((takeEntrySem ![v]).length +
(match dropEntrySem ![v] with
| [] => []
| b :: tail => [b]).length) +
((dropEntrySem ![v]).length - 1) ≤
v.length + 1] true v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.length⊢ 2 *
((takeEntrySem ![v]).length +
(match dropEntrySem ![v] with
| [] => []
| b :: tail => [b]).length) +
((dropEntrySem ![v]).length - 1) ≤
v.length + 1
match hd : dropEntrySem ![v] with
| [] => v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.lengthhd:dropEntrySem ![v] = []⊢ 2 *
((takeEntrySem ![v]).length +
(match [] with
| [] => []
| b :: tail => [b]).length) +
([].length - 1) ≤
v.length + 1
rw [hd v:List Boolih:2 * (takeEntrySem ![v]).length + [].length ≤ v.lengthhd:dropEntrySem ![v] = []⊢ 2 *
((takeEntrySem ![v]).length +
(match [] with
| [] => []
| b :: tail => [b]).length) +
([].length - 1) ≤
v.length + 1] at ih v:List Boolih:2 * (takeEntrySem ![v]).length + [].length ≤ v.lengthhd:dropEntrySem ![v] = []⊢ 2 *
((takeEntrySem ![v]).length +
(match [] with
| [] => []
| b :: tail => [b]).length) +
([].length - 1) ≤
v.length + 1
simp only [List.length_nil] v:List Boolih:2 * (takeEntrySem ![v]).length + [].length ≤ v.lengthhd:dropEntrySem ![v] = []⊢ 2 * ((takeEntrySem ![v]).length + 0) + (0 - 1) ≤ v.length + 1
omega All goals completed! 🐙
| c :: t => v:List Boolih:2 * (takeEntrySem ![v]).length + (dropEntrySem ![v]).length ≤ v.lengthc:Boolt:List Boolhd:dropEntrySem ![v] = c :: t⊢ 2 *
((takeEntrySem ![v]).length +
(match c :: t with
| [] => []
| b :: tail => [b]).length) +
((c :: t).length - 1) ≤
v.length + 1
rw [hd, v:List Boolc:Boolt:List Boolih:2 * (takeEntrySem ![v]).length + (c :: t).length ≤ v.lengthhd:dropEntrySem ![v] = c :: t⊢ 2 *
((takeEntrySem ![v]).length +
(match c :: t with
| [] => []
| b :: tail => [b]).length) +
((c :: t).length - 1) ≤
v.length + 1 List.length_cons v:List Boolc:Boolt:List Boolih:2 * (takeEntrySem ![v]).length + (t.length + 1) ≤ v.lengthhd:dropEntrySem ![v] = c :: t⊢ 2 *
((takeEntrySem ![v]).length +
(match c :: t with
| [] => []
| b :: tail => [b]).length) +
((c :: t).length - 1) ≤
v.length + 1] at ih v:List Boolc:Boolt:List Boolih:2 * (takeEntrySem ![v]).length + (t.length + 1) ≤ v.lengthhd:dropEntrySem ![v] = c :: t⊢ 2 *
((takeEntrySem ![v]).length +
(match c :: t with
| [] => []
| b :: tail => [b]).length) +
((c :: t).length - 1) ≤
v.length + 1
simp only [List.length_cons, List.length_nil] v:List Boolc:Boolt:List Boolih:2 * (takeEntrySem ![v]).length + (t.length + 1) ≤ v.lengthhd:dropEntrySem ![v] = c :: t⊢ 2 * ((takeEntrySem ![v]).length + (0 + 1)) + (t.length + 1 - 1) ≤ v.length + 1
omega All goals completed! 🐙The payload of a self-delimiting entry, as an expression of arity one.
def takeEntryOf : COf 1 :=
scan2Of (zeroAtOf 0) (zeroAtOf 2)
(concatCompOf 2 (comp1Of firstBitOf (comp1Of dropEntryOf (projOf 2 0)))
(projOf 2 1)) length_takeEntrySem_leThe payload expression's value at a step.
@[simp] theorem stepWord_takeEntryOf (w : List Bool) :
stepWord takeEntryOf w = takeEntrySem ![w] := rflA composition's value at an arity-one step.
theorem stepWord_compOf {m : ℕ} (head : COf m) (args : Fin m → COf 1)
(u : List Bool) :
stepWord (compOf head args) u =
semAt m head.1.1 head.2 fun i ↦ stepWord (args i) u :=
semAt_compOf head args ![u]An arity-one composition's value at an arity-one step.
theorem stepWord_comp1Of (e a : COf 1) (u : List Bool) :
stepWord (comp1Of e a) u = stepWord e (stepWord a u) :=
semAt_comp1Of e a ![u]A concatenation's value at an arity-one step.
theorem stepWord_concatCompOf (a b : COf 1) (u : List Bool) :
stepWord (concatCompOf 1 a b) u = stepWord b u ++ stepWord a u :=
semAt_concatCompOf 1 a b ![u]The identity, as an expression of arity one: the sole projection at that arity, named for the use it is put to.
The identity's value at a step.
@[simp] theorem stepWord_idOf (u : List Bool) : stepWord idOf u = u :=
semAt_projOf 1 0 ![u]
The leading run of true of a word.
The run primitive on the empty word.
theorem takeUnarySem_nil : takeUnarySem ![[]] = [] := rfl
What the run primitive computes: a true extends the run, a false ends
it.
theorem takeUnarySem_cons (b : Bool) (v : List Bool) :
takeUnarySem ![b :: v] = if b then true :: takeUnarySem ![v] else [] := by b:Boolv:List Bool⊢ takeUnarySem ![b :: v] = if b = true then true :: takeUnarySem ![v] else []
change scan2Sem _ _ _ ![b :: v] = _ b:Boolv:List Bool⊢ scan2Sem (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1)) ![b :: v] =
if b = true then true :: takeUnarySem ![v] else []
rw [scan2Sem_cons b:Boolv:List Bool⊢ step2Word (if b = true then prependOf [true] (projOf 2 1) else zeroAtOf 2) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1)) ![v]) =
if b = true then true :: takeUnarySem ![v] else []] b:Boolv:List Bool⊢ step2Word (if b = true then prependOf [true] (projOf 2 1) else zeroAtOf 2) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1)) ![v]) =
if b = true then true :: takeUnarySem ![v] else []
cases b false v:List Bool⊢ step2Word (if false = true then prependOf [true] (projOf 2 1) else zeroAtOf 2) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1)) ![v]) =
if false = true then true :: takeUnarySem ![v] else []true v:List Bool⊢ step2Word (if true = true then prependOf [true] (projOf 2 1) else zeroAtOf 2) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1)) ![v]) =
if true = true then true :: takeUnarySem ![v] else []
· false v:List Bool⊢ step2Word (if false = true then prependOf [true] (projOf 2 1) else zeroAtOf 2) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1)) ![v]) =
if false = true then true :: takeUnarySem ![v] else [] exact step2Word_constAtOf [] v _ All goals completed! 🐙
· true v:List Bool⊢ step2Word (if true = true then prependOf [true] (projOf 2 1) else zeroAtOf 2) v
(scan2Sem (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1)) ![v]) =
if true = true then true :: takeUnarySem ![v] else [] exact (step2Word_prependOf (projOf 2 1) v _ [true]).trans
(congrArg (fun t ↦ true :: t) (step2Word_projOf 1 v _)) All goals completed! 🐙The run primitive never lengthens its argument.
theorem length_takeUnarySem_le : ∀ w : List Bool,
(takeUnarySem ![w]).length ≤ w.length :=
List.rec (Nat.le_refl 0) fun b v ih ↦ by b:Boolv:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (takeUnarySem ![b :: v]).length ≤ (b :: v).length
rw [takeUnarySem_cons, b:Boolv:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (if b = true then true :: takeUnarySem ![v] else []).length ≤ (b :: v).length List.length_cons b:Boolv:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (if b = true then true :: takeUnarySem ![v] else []).length ≤ v.length + 1] b:Boolv:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (if b = true then true :: takeUnarySem ![v] else []).length ≤ v.length + 1
cases b false v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (if false = true then true :: takeUnarySem ![v] else []).length ≤ v.length + 1true v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (if true = true then true :: takeUnarySem ![v] else []).length ≤ v.length + 1
· false v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (if false = true then true :: takeUnarySem ![v] else []).length ≤ v.length + 1 rw [ite_eq_right (by v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ ¬false = true simp All goals completed! 🐙), List.length_nil false v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ 0 ≤ v.length + 1] false v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ 0 ≤ v.length + 1
omega All goals completed! 🐙
· true v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (if true = true then true :: takeUnarySem ![v] else []).length ≤ v.length + 1 rw [ite_eq_left rfl, true v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (true :: takeUnarySem ![v]).length ≤ v.length + 1 List.length_cons true v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (takeUnarySem ![v]).length + 1 ≤ v.length + 1] true v:List Boolih:(takeUnarySem ![v]).length ≤ v.length⊢ (takeUnarySem ![v]).length + 1 ≤ v.length + 1
omega All goals completed! 🐙
The leading run of true, as an expression of arity one.
def takeUnaryOf : COf 1 :=
scan2Of (zeroAtOf 0) (zeroAtOf 2) (prependOf [true] (projOf 2 1))
length_takeUnarySem_leThe run expression's value at a step.
@[simp] theorem stepWord_takeUnaryOf (w : List Bool) :
stepWord takeUnaryOf w = takeUnarySem ![w] := rflThe run primitive returns the unary prefix a word carries.
theorem takeUnarySem_replicate (X : List Bool) : ∀ k : ℕ,
takeUnarySem ![List.replicate k true ++ false :: X] = List.replicate k true :=
Nat.rec (by X:List Bool⊢ takeUnarySem ![List.replicate Nat.zero true ++ false :: X] = List.replicate Nat.zero true rw [List.replicate_zero, X:List Bool⊢ takeUnarySem ![[] ++ false :: X] = [] List.nil_append, X:List Bool⊢ takeUnarySem ![false :: X] = [] takeUnarySem_cons, X:List Bool⊢ (if false = true then true :: takeUnarySem ![X] else []) = []
ite_eq_right (by X:List Bool⊢ ¬false = true simp All goals completed! 🐙)] All goals completed! 🐙)
fun k ih ↦ by X:List Boolk:ℕih:takeUnarySem ![List.replicate k true ++ false :: X] = List.replicate k true⊢ takeUnarySem ![List.replicate k.succ true ++ false :: X] = List.replicate k.succ true
rw [List.replicate_succ, X:List Boolk:ℕih:takeUnarySem ![List.replicate k true ++ false :: X] = List.replicate k true⊢ takeUnarySem ![true :: List.replicate k true ++ false :: X] = true :: List.replicate k true List.cons_append, X:List Boolk:ℕih:takeUnarySem ![List.replicate k true ++ false :: X] = List.replicate k true⊢ takeUnarySem ![true :: (List.replicate k true ++ false :: X)] = true :: List.replicate k true takeUnarySem_cons, X:List Boolk:ℕih:takeUnarySem ![List.replicate k true ++ false :: X] = List.replicate k true⊢ (if true = true then true :: takeUnarySem ![List.replicate k true ++ false :: X] else []) =
true :: List.replicate k true ite_eq_left rfl, X:List Boolk:ℕih:takeUnarySem ![List.replicate k true ++ false :: X] = List.replicate k true⊢ true :: takeUnarySem ![List.replicate k true ++ false :: X] = true :: List.replicate k true
ih X:List Boolk:ℕih:takeUnarySem ![List.replicate k true ++ false :: X] = List.replicate k true⊢ true :: List.replicate k true = true :: List.replicate k true] All goals completed! 🐙Dropping a fixed number of whole self-delimiting entries.
def dropEntriesOf : ℕ → COf 1 :=
Nat.rec idOf fun _ ih ↦ comp1Of ih dropEntryOfDropping no entries is the identity.
@[simp] theorem dropEntriesOf_zero : dropEntriesOf 0 = idOf := rflDropping one more entry drops one first.
theorem stepWord_dropEntriesOf_succ (k : ℕ) (u : List Bool) :
stepWord (dropEntriesOf (k + 1)) u =
stepWord (dropEntriesOf k) (dropEntrySem ![u]) :=
stepWord_comp1Of _ _ u
The payload of the j-th self-delimiting entry.
def entryOf (j : ℕ) : COf 1 := comp1Of takeEntryOf (dropEntriesOf j)
The j-th entry is the payload past j dropped entries.
theorem stepWord_entryOf (j : ℕ) (u : List Bool) :
stepWord (entryOf j) u = takeEntrySem ![stepWord (dropEntriesOf j) u] :=
stepWord_comp1Of _ _ u
The self-delimiting spelling of a payload: its length in unary, a false
sentinel, then the payload.
def entryWord (u : List Bool) : List Bool :=
List.replicate u.length true ++ false :: uAn entry's length: twice the payload's, plus the sentinel.
@[simp] theorem length_entryWord (u : List Bool) :
(entryWord u).length = 2 * u.length + 1 := by u:List Bool⊢ (entryWord u).length = 2 * u.length + 1
rw [entryWord, u:List Bool⊢ (List.replicate u.length true ++ false :: u).length = 2 * u.length + 1 List.length_append, u:List Bool⊢ (List.replicate u.length true).length + (false :: u).length = 2 * u.length + 1 List.length_replicate, u:List Bool⊢ u.length + (false :: u).length = 2 * u.length + 1 List.length_cons u:List Bool⊢ u.length + (u.length + 1) = 2 * u.length + 1] u:List Bool⊢ u.length + (u.length + 1) = 2 * u.length + 1
omega All goals completed! 🐙The first-bit primitive is the one-bit truncation.
theorem firstBitSem_eq_take_one : ∀ z : List Bool, firstBitSem ![z] = z.take 1
| [] => rfl
| b :: t => b:Boolt:List Bool⊢ firstBitSem ![b :: t] = List.take 1 (b :: t) by b:Boolt:List Bool⊢ firstBitSem ![b :: t] = List.take 1 (b :: t)
rw [firstBitSem_eq (b :: t) b:Boolt:List Bool⊢ (match b :: t with
| [] => []
| b :: tail => [b]) =
List.take 1 (b :: t)] b:Boolt:List Bool⊢ (match b :: t with
| [] => []
| b :: tail => [b]) =
List.take 1 (b :: t)
rfl All goals completed! 🐙The prefix-dropping primitive reads a unary prefix off and returns what follows the sentinel.
theorem dropUnarySem_replicate (X : List Bool) : ∀ k : ℕ,
dropUnarySem ![List.replicate k true ++ false :: X] = X :=
Nat.rec rfl fun k ih ↦ by X:List Boolk:ℕih:dropUnarySem ![List.replicate k true ++ false :: X] = X⊢ dropUnarySem ![List.replicate k.succ true ++ false :: X] = X
rw [List.replicate_succ, X:List Boolk:ℕih:dropUnarySem ![List.replicate k true ++ false :: X] = X⊢ dropUnarySem ![true :: List.replicate k true ++ false :: X] = X List.cons_append, X:List Boolk:ℕih:dropUnarySem ![List.replicate k true ++ false :: X] = X⊢ dropUnarySem ![true :: (List.replicate k true ++ false :: X)] = X dropUnarySem_cons, X:List Boolk:ℕih:dropUnarySem ![List.replicate k true ++ false :: X] = X⊢ (if true = true then dropUnarySem ![List.replicate k true ++ false :: X] else List.replicate k true ++ false :: X) = X ite_eq_left rfl, X:List Boolk:ℕih:dropUnarySem ![List.replicate k true ++ false :: X] = X⊢ dropUnarySem ![List.replicate k true ++ false :: X] = X ih X:List Boolk:ℕih:dropUnarySem ![List.replicate k true ++ false :: X] = X⊢ X = X] All goals completed! 🐙The entry-dropping primitive drops as many payload bits as the unary prefix counts.
theorem dropEntrySem_replicate (X : List Bool) : ∀ k : ℕ,
dropEntrySem ![List.replicate k true ++ false :: X] = X.drop k :=
Nat.rec (by X:List Bool⊢ dropEntrySem ![List.replicate Nat.zero true ++ false :: X] = List.drop Nat.zero X rw [List.replicate_zero, X:List Bool⊢ dropEntrySem ![[] ++ false :: X] = List.drop Nat.zero X List.nil_append, X:List Bool⊢ dropEntrySem ![false :: X] = List.drop Nat.zero X dropEntrySem_cons, X:List Bool⊢ (if false = true then (dropEntrySem ![X]).tail else X) = List.drop Nat.zero X
ite_eq_right (by X:List Bool⊢ ¬false = true simp All goals completed! 🐙), List.drop_zero X:List Bool⊢ X = X] All goals completed! 🐙)
fun k ih ↦ by X:List Boolk:ℕih:dropEntrySem ![List.replicate k true ++ false :: X] = List.drop k X⊢ dropEntrySem ![List.replicate k.succ true ++ false :: X] = List.drop k.succ X
rw [List.replicate_succ, X:List Boolk:ℕih:dropEntrySem ![List.replicate k true ++ false :: X] = List.drop k X⊢ dropEntrySem ![true :: List.replicate k true ++ false :: X] = List.drop k.succ X List.cons_append, X:List Boolk:ℕih:dropEntrySem ![List.replicate k true ++ false :: X] = List.drop k X⊢ dropEntrySem ![true :: (List.replicate k true ++ false :: X)] = List.drop k.succ X dropEntrySem_cons, X:List Boolk:ℕih:dropEntrySem ![List.replicate k true ++ false :: X] = List.drop k X⊢ (if true = true then (dropEntrySem ![List.replicate k true ++ false :: X]).tail
else List.replicate k true ++ false :: X) =
List.drop k.succ X ite_eq_left rfl, X:List Boolk:ℕih:dropEntrySem ![List.replicate k true ++ false :: X] = List.drop k X⊢ (dropEntrySem ![List.replicate k true ++ false :: X]).tail = List.drop k.succ X
ih, X:List Boolk:ℕih:dropEntrySem ![List.replicate k true ++ false :: X] = List.drop k X⊢ (List.drop k X).tail = List.drop k.succ X List.tail_drop X:List Boolk:ℕih:dropEntrySem ![List.replicate k true ++ false :: X] = List.drop k X⊢ List.drop (k + 1) X = List.drop k.succ X] All goals completed! 🐙
Splitting a truncation at its last bit. Proved here rather than by
List.take_add, which was measured to depend on Classical.choice.
theorem take_succ_append_take_one : ∀ (k : ℕ) (X : List Bool),
X.take (k + 1) = X.take k ++ (X.drop k).take 1 :=
Nat.rec (fun X ↦ by X:List Bool⊢ List.take (Nat.zero + 1) X = List.take Nat.zero X ++ List.take 1 (List.drop Nat.zero X) rw [List.take_zero, X:List Bool⊢ List.take (Nat.zero + 1) X = [] ++ List.take 1 (List.drop Nat.zero X) List.nil_append, X:List Bool⊢ List.take (Nat.zero + 1) X = List.take 1 (List.drop Nat.zero X) List.drop_zero X:List Bool⊢ List.take (Nat.zero + 1) X = List.take 1 X] All goals completed! 🐙)
fun k ih X ↦ match X with
| [] => rfl
| b :: t => k:ℕih:∀ (X : List Bool), List.take (k + 1) X = List.take k X ++ List.take 1 (List.drop k X)X:List Boolb:Boolt:List Bool⊢ List.take (k.succ + 1) (b :: t) = List.take k.succ (b :: t) ++ List.take 1 (List.drop k.succ (b :: t)) by k:ℕih:∀ (X : List Bool), List.take (k + 1) X = List.take k X ++ List.take 1 (List.drop k X)X:List Boolb:Boolt:List Bool⊢ List.take (k.succ + 1) (b :: t) = List.take k.succ (b :: t) ++ List.take 1 (List.drop k.succ (b :: t))
rw [List.take_succ_cons, k:ℕih:∀ (X : List Bool), List.take (k + 1) X = List.take k X ++ List.take 1 (List.drop k X)X:List Boolb:Boolt:List Bool⊢ b :: List.take (k + 1) t = List.take k.succ (b :: t) ++ List.take 1 (List.drop k.succ (b :: t)) List.take_succ_cons, k:ℕih:∀ (X : List Bool), List.take (k + 1) X = List.take k X ++ List.take 1 (List.drop k X)X:List Boolb:Boolt:List Bool⊢ b :: List.take (k + 1) t = b :: List.take k t ++ List.take 1 (List.drop k.succ (b :: t)) List.drop_succ_cons, k:ℕih:∀ (X : List Bool), List.take (k + 1) X = List.take k X ++ List.take 1 (List.drop k X)X:List Boolb:Boolt:List Bool⊢ b :: List.take (k + 1) t = b :: List.take k t ++ List.take 1 (List.drop k t)
List.cons_append, k:ℕih:∀ (X : List Bool), List.take (k + 1) X = List.take k X ++ List.take 1 (List.drop k X)X:List Boolb:Boolt:List Bool⊢ b :: List.take (k + 1) t = b :: (List.take k t ++ List.take 1 (List.drop k t)) ih t k:ℕih:∀ (X : List Bool), List.take (k + 1) X = List.take k X ++ List.take 1 (List.drop k X)X:List Boolb:Boolt:List Bool⊢ b :: (List.take k t ++ List.take 1 (List.drop k t)) = b :: (List.take k t ++ List.take 1 (List.drop k t))] All goals completed! 🐙The payload primitive reads exactly as many bits as the unary prefix counts.
theorem takeEntrySem_replicate (X : List Bool) : ∀ k : ℕ,
takeEntrySem ![List.replicate k true ++ false :: X] = X.take k :=
Nat.rec (by X:List Bool⊢ takeEntrySem ![List.replicate Nat.zero true ++ false :: X] = List.take Nat.zero X rw [List.replicate_zero, X:List Bool⊢ takeEntrySem ![[] ++ false :: X] = List.take Nat.zero X List.nil_append, X:List Bool⊢ takeEntrySem ![false :: X] = List.take Nat.zero X takeEntrySem_cons, X:List Bool⊢ (if false = true then takeEntrySem ![X] ++ firstBitSem ![dropEntrySem ![X]] else []) = List.take Nat.zero X
ite_eq_right (by X:List Bool⊢ ¬false = true simp All goals completed! 🐙), List.take_zero X:List Bool⊢ [] = []] All goals completed! 🐙)
fun k ih ↦ by X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ takeEntrySem ![List.replicate k.succ true ++ false :: X] = List.take k.succ X
rw [List.replicate_succ, X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ takeEntrySem ![true :: List.replicate k true ++ false :: X] = List.take k.succ X List.cons_append, X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ takeEntrySem ![true :: (List.replicate k true ++ false :: X)] = List.take k.succ X takeEntrySem_cons, X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ (if true = true then
takeEntrySem ![List.replicate k true ++ false :: X] ++
firstBitSem ![dropEntrySem ![List.replicate k true ++ false :: X]]
else []) =
List.take k.succ X ite_eq_left rfl, X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ takeEntrySem ![List.replicate k true ++ false :: X] ++
firstBitSem ![dropEntrySem ![List.replicate k true ++ false :: X]] =
List.take k.succ X
ih, X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ List.take k X ++ firstBitSem ![dropEntrySem ![List.replicate k true ++ false :: X]] = List.take k.succ X dropEntrySem_replicate, X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ List.take k X ++ firstBitSem ![List.drop k X] = List.take k.succ X firstBitSem_eq_take_one, X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ List.take k X ++ List.take 1 (List.drop k X) = List.take k.succ X
← take_succ_append_take_one X:List Boolk:ℕih:takeEntrySem ![List.replicate k true ++ false :: X] = List.take k X⊢ List.take (k + 1) X = List.take k.succ X] All goals completed! 🐙The payload primitive returns an entry's payload, whatever follows it.
theorem takeEntrySem_entryWord (u rest : List Bool) :
takeEntrySem ![entryWord u ++ rest] = u := by u:List Boolrest:List Bool⊢ takeEntrySem ![entryWord u ++ rest] = u
rw [entryWord, u:List Boolrest:List Bool⊢ takeEntrySem ![List.replicate u.length true ++ false :: u ++ rest] = u List.append_assoc, u:List Boolrest:List Bool⊢ takeEntrySem ![List.replicate u.length true ++ (false :: u ++ rest)] = u List.cons_append, u:List Boolrest:List Bool⊢ takeEntrySem ![List.replicate u.length true ++ false :: (u ++ rest)] = u takeEntrySem_replicate, u:List Boolrest:List Bool⊢ List.take u.length (u ++ rest) = u
List.take_left u:List Boolrest:List Bool⊢ u = u] All goals completed! 🐙The entry-dropping primitive returns whatever follows an entry.
theorem dropEntrySem_entryWord (u rest : List Bool) :
dropEntrySem ![entryWord u ++ rest] = rest := by u:List Boolrest:List Bool⊢ dropEntrySem ![entryWord u ++ rest] = rest
rw [entryWord, u:List Boolrest:List Bool⊢ dropEntrySem ![List.replicate u.length true ++ false :: u ++ rest] = rest List.append_assoc, u:List Boolrest:List Bool⊢ dropEntrySem ![List.replicate u.length true ++ (false :: u ++ rest)] = rest List.cons_append, u:List Boolrest:List Bool⊢ dropEntrySem ![List.replicate u.length true ++ false :: (u ++ rest)] = rest dropEntrySem_replicate, u:List Boolrest:List Bool⊢ List.drop u.length (u ++ rest) = rest
List.drop_left u:List Boolrest:List Bool⊢ rest = rest] All goals completed! 🐙end Geb.CobhamFoldend