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.Bound public import Geb.Prototypes.Computability.CobhamFoldProto.Layout

The fold over recognized terms as an expression of Cobham's class

The fold scan of Geb/Prototypes/Computability/CobhamFoldProto/Fold.lean, laid out as a bitstring by Geb/Prototypes/Computability/CobhamFoldProto/Layout.lean, carried by the scan combinator of Geb/Prototypes/Computability/CobhamFoldProto/Bound.lean, and composed with a readout into an expression computing RankedAlphabet.parse followed by the fold.

At p = 0 and the carrier Unit this construction meets the recognizer of Geb/Mathlib/Computability/Cobham/RankedTree.lean; the module Geb/Prototypes/Computability/CobhamFoldProto/Degenerate.lean identifies the state layout, the dispatch window, the readout window and the step, and the two accept the same language. They are not the same expression. The raw trees differ — Geb.CobhamFold.boundMulRaw_ne_boundRaw separates the two bound children at multiplicity one, at every growth — and the rejecting words differ, this module's outWord spelling both branches at the width p + 1 where Cobham.isRankedSem_eq_ite gives the empty bitstring.

Main definitions

    Geb.CobhamFold.foldStepF — one step of the scan, as an expression of arity one.

    Geb.CobhamFold.foldGrowth — the growth the state layout's fixed part contributes.

    Geb.CobhamFold.foldSemF — the meaning of the scan.

    Geb.CobhamFold.foldExprF, Geb.CobhamFold.foldExprOfF — the scan as an expression of Cobham.C, and at its declared arity.

    Geb.CobhamFold.readoutWidth, Geb.CobhamFold.outWord, Geb.CobhamFold.readState, Geb.CobhamFold.readOf — the readout's window, its output word, the Option it reads off the window, and the readout as an expression.

    Geb.CobhamFold.foldOutOf, Geb.CobhamFold.foldOutExpr, Geb.CobhamFold.foldOutSem — the readout composed onto the scan by Geb.CobhamFold.comp1Of.

Main statements

    Geb.CobhamFold.stepWord_foldStepF_of_lt — a step of the expression computes a step of the fold scan.

    Geb.CobhamFold.foldSemF_eq — the expression computes the fold scan's state word on every input.

    Geb.CobhamFold.length_foldSemF_le — the recursion bound the scan combinator asks for, at a multiplier covering one stack entry per symbol block.

    Geb.CobhamFold.length_outWord, Geb.CobhamFold.headD_outWord, Geb.CobhamFold.bits_tail_outWord — the output's width, the marker separating its two branches, and the recoverability of the value.

    Geb.CobhamFold.stepWord_readOf — the readout's value at the state it reads.

    Geb.CobhamFold.foldOutSem_eq — the composition computes Geb.CobhamFold.foldOut, spelled by outWord.

    Geb.CobhamFold.foldOutSem_eq_parse — the same value read as RankedAlphabet.parse followed by the algebra morphism.

    Geb.CobhamFold.foldSemF_eq_eval, Geb.CobhamFold.foldOutSem_eq_eval — the meanings read at the raw trees are the meanings the expressions carry.

Implementation notes

The multiplier is a parameter constrained by p + 1 ≤ mult * R.width, rather than fixed at p + 1. The state carries one (p + 1)-bit entry per pending subterm and the pending count rises once per R.width input bits — that is Geb.CobhamFold.width_mul_depth_scanFinal_le — so any multiplier meeting the inequality bounds the state. mult = p + 1 always meets it, RankedAlphabet.width_pos giving 1 ≤ R.width; a wide alphabet admits a smaller one.

The readout reads two stack entries: one to carry the value, and one more whose marker distinguishes a stack of exactly one entry from a longer one. That is the Cobham.acceptWord R ++ [false] of the recognizer's verdict test, one entry wide rather than one bit wide.

outWord spells none as a false marker followed by p false bits, so both branches have the width p + 1, and the marker alone separates them. A rejected word receives that word rather than merely something other than an accepted one, which is the discipline Cobham.isRankedSem_eq_ite records.

readState tests the decoded state's three fields rather than matching on its stack: a match whose pattern fixes the stack's length does not reduce at a variable stack.

References

    [Cobham1965]

Tags

Cobham, bounded recursion on notation, ranked alphabet, fold, catamorphism

@[expose] public sectionnamespace Geb.CobhamFoldopen Cobham RankedAlphabetuniverse uvariable {α : Type u} {p : }

One step of the fold expression: dispatch on the state's leading bits, prepend the rebuilt prefix and drop the consumed bits. Every branch has that one shape.

def foldStepF (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (b : Bool) : COf 1 := diagOf (casesOf (dispatchWidthF R p) fun v prependOf (nextPrefixF R enc alg b (decodeStateF R p dec v)) (predIterOf (dropCountF R p b (decodeStateF R p dec v))))

A step of the expression computes a step of the fold scan, on a state whose incomplete block is short of the width. This is where the decoder, the two truncation lemmas and the step lemma meet.

theorem stepWord_foldStepF_of_lt (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (b : Bool) (s : FoldScan α) (h : s.buf.length < R.width) : stepWord (foldStepF R p enc dec alg b) (stateWordF R enc s) = stateWordF R enc (foldScanStep R alg b s) := α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Bools:FoldScan αh:s.buf.length < R.widthstepWord (foldStepF R p enc dec alg b) (stateWordF R enc s) = stateWordF R enc (foldScanStep R alg b s) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Bools:FoldScan αh:s.buf.length < R.widthsemAt 2 (casesOf (dispatchWidthF R p) fun v prependOf (nextPrefixF R enc alg b (decodeStateF R p dec v)) (predIterOf (dropCountF R p b (decodeStateF R p dec v)))) ![stateWordF R enc s, stateWordF R enc s] = stateWordF R enc (foldScanStep R alg b s) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αb:Bools:FoldScan αh:s.buf.length < R.widthcasesSem (dispatchWidthF R p) (fun v prependOf (nextPrefixF R enc alg b (decodeStateF R p dec v)) (predIterOf (dropCountF R p b (decodeStateF R p dec v)))) ![stateWordF R enc s, stateWordF R enc s] = stateWordF R enc (foldScanStep R alg b s) All goals completed! 🐙

The growth the state layout's fixed part contributes: the flag and the slot.

def foldGrowth (R : RankedAlphabet) : := 1 + R.width

The fold expression's scan, at the two steps and the multiplicative bound.

def foldSemF (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) : Sem 1 := scanBSem (constAtOf 0 (stateWordF R enc [], [], true)) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) (wValid_boundMulRaw mult (foldGrowth R)) (wIndexRoot_boundMulRaw mult (foldGrowth R))

The expression computes the fold scan's state word on every input.

theorem foldSemF_eq (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (w : List Bool) : foldSemF R p enc dec alg mult ![w] = stateWordF R enc (foldScanFinal R alg w) := α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List BoolfoldSemF R p enc dec alg mult ![w] = stateWordF R enc (foldScanFinal R alg w) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List BoolList.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) w = stateWordF R enc (foldScanFinal R alg w) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List BoolList.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) [] = stateWordF R enc (foldScanFinal R alg [])α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Bool (head : Bool) (tail : List Bool), List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) tail = stateWordF R enc (foldScanFinal R alg tail) List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) (head :: tail) = stateWordF R enc (foldScanFinal R alg (head :: tail)) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List BoolList.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) [] = stateWordF R enc (foldScanFinal R alg []) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List BoolstateWordF R enc { buf := [], stack := [], live := true } = stateWordF R enc (foldScanFinal R alg []) All goals completed! 🐙 α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Bool (head : Bool) (tail : List Bool), List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) tail = stateWordF R enc (foldScanFinal R alg tail) List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) (head :: tail) = stateWordF R enc (foldScanFinal R alg (head :: tail)) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Boolb:Boolv:List Boolih:List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) v = stateWordF R enc (foldScanFinal R alg v)List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) (b :: v) = stateWordF R enc (foldScanFinal R alg (b :: v)) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Boolb:Boolv:List Boolih:List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) v = stateWordF R enc (foldScanFinal R alg v)scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) b (stateWordF R enc (foldScanFinal R alg v)) = stateWordF R enc (foldScanFinal R alg (b :: v)) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Boolv:List Boolih:List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) v = stateWordF R enc (foldScanFinal R alg v)scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) false (stateWordF R enc (foldScanFinal R alg v)) = stateWordF R enc (foldScanFinal R alg (false :: v))α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Boolv:List Boolih:List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) v = stateWordF R enc (foldScanFinal R alg v)scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) true (stateWordF R enc (foldScanFinal R alg v)) = stateWordF R enc (foldScanFinal R alg (true :: v)) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Boolv:List Boolih:List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) v = stateWordF R enc (foldScanFinal R alg v)scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) false (stateWordF R enc (foldScanFinal R alg v)) = stateWordF R enc (foldScanFinal R alg (false :: v)) All goals completed! 🐙 α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:w:List Boolv:List Boolih:List.foldr (scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true)) (baseWord (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true }))) v = stateWordF R enc (foldScanFinal R alg v)scanStepWord (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) true (stateWordF R enc (foldScanFinal R alg v)) = stateWordF R enc (foldScanFinal R alg (true :: v)) All goals completed! 🐙

The recursion bound the scan combinator asks for. The state carries one (p + 1)-bit entry per pending subterm, and the pending count rises once per R.width input bits, so a multiplier covering one entry per block bounds the state. Stated at scanBSem, which is the form scanMul consumes.

theorem length_foldSemF_le (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) (w : List Bool) : (scanBSem (constAtOf 0 (stateWordF R enc [], [], true)) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) (wValid_boundMulRaw mult (foldGrowth R)) (wIndexRoot_boundMulRaw mult (foldGrowth R)) ![w]).length mult * w.length + foldGrowth R := α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List Bool(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length mult * w.length + foldGrowth R α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List Boolhstate:(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length = 1 + R.width + (p + 1) * (R.scanFinal w).depth(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length mult * w.length + foldGrowth R α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List Boolhstate:(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length = 1 + R.width + (p + 1) * (R.scanFinal w).depthhd:R.width * (R.scanFinal w).depth w.length(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length mult * w.length + foldGrowth R α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List Boolhstate:(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length = 1 + R.width + (p + 1) * (R.scanFinal w).depthhd:R.width * (R.scanFinal w).depth w.lengthh1:(p + 1) * (R.scanFinal w).depth mult * R.width * (R.scanFinal w).depth(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length mult * w.length + foldGrowth R α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List Boolhstate:(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length = 1 + R.width + (p + 1) * (R.scanFinal w).depthhd:R.width * (R.scanFinal w).depth w.lengthh1:(p + 1) * (R.scanFinal w).depth mult * R.width * (R.scanFinal w).depthh2:mult * R.width * (R.scanFinal w).depth = mult * (R.width * (R.scanFinal w).depth)(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length mult * w.length + foldGrowth R α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List Boolhstate:(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length = 1 + R.width + (p + 1) * (R.scanFinal w).depthhd:R.width * (R.scanFinal w).depth w.lengthh1:(p + 1) * (R.scanFinal w).depth mult * R.width * (R.scanFinal w).depthh2:mult * R.width * (R.scanFinal w).depth = mult * (R.width * (R.scanFinal w).depth)h3:mult * (R.width * (R.scanFinal w).depth) mult * w.length(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length mult * w.length + foldGrowth R α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List Boolhstate:(scanBSem (constAtOf 0 (stateWordF R enc { buf := [], stack := [], live := true })) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) (boundMulRaw mult (foldGrowth R)) ![w]).length = 1 + R.width + (p + 1) * (R.scanFinal w).depthhd:R.width * (R.scanFinal w).depth w.lengthh1:(p + 1) * (R.scanFinal w).depth mult * R.width * (R.scanFinal w).depthh2:mult * R.width * (R.scanFinal w).depth = mult * (R.width * (R.scanFinal w).depth)h3:mult * (R.width * (R.scanFinal w).depth) mult * w.length1 + R.width + (p + 1) * (R.scanFinal w).depth mult * w.length + (1 + R.width) All goals completed! 🐙

The scan as a member of Cobham.C, at its arity: the form consumers take, foldExprF being its underlying expression.

def foldExprOfF (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) : COf 1 := scanMulOf (constAtOf 0 (stateWordF R enc [], [], true)) (foldStepF R p enc dec alg false) (foldStepF R p enc dec alg true) mult (foldGrowth R) (length_foldSemF_le R p enc dec hdec alg mult hmult)

The scan as an expression of Cobham's class, its recursion bound discharged by length_foldSemF_le.

def foldExprF (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) : C := (foldExprOfF R p enc dec hdec alg mult hmult).1

The meaning foldSemF reads at the raw tree is the meaning foldExprF carries.

theorem foldSemF_eq_eval (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) : transport (foldExprOfF R p enc dec hdec alg mult hmult).2 (foldExprOfF R p enc dec hdec alg mult hmult).1.eval = foldSemF R p enc dec alg mult := rfl

The number of state bits the readout dispatches on: the flag, the slot, and two stack entries.

def readoutWidth (R : RankedAlphabet) (p : ) : := 1 + R.width + (p + 1) * 2

The readout's output word: a marked encoding at a value, and a false marker followed by p false bits at none. Both branches have width p + 1.

def outWord (enc : α Fin p Bool) : Option α List Bool | none => false :: List.replicate p false | some a => entryBits enc a

Both branches of the output have an entry's width, so the leading marker alone separates them.

theorem length_outWord (enc : α Fin p Bool) : x : Option α, (outWord enc x).length = p + 1 α:Type up:enc:α Fin p Bool(outWord enc none).length = p + 1 α:Type up:enc:α Fin p Bool(outWord enc none).length = p + 1 All goals completed! 🐙 | some a => length_entryBits enc a

The output's leading marker is set exactly at a value, so a consumer separates the two branches by one bit.

theorem headD_outWord (enc : α Fin p Bool) : x : Option α, (outWord enc x).headD false = x.isSome | none => rfl | some _ => rfl

The carrier value is recoverable from the output: past the marker the output is the encoding, which a retraction inverts.

theorem bits_tail_outWord (enc : α Fin p Bool) (a : α) : bits p (outWord enc (some a)).tail = enc a := α:Type up:enc:α Fin p Boola:αbits p (outWord enc (some a)).tail = enc a All goals completed! 🐙

The Option the readout reads off its window: the top of the stack when the state is live, carries no incomplete block and holds exactly one entry. The three tests are those of Geb.CobhamFold.foldOut.

def readState (R : RankedAlphabet) (p : ) (dec : (Fin p Bool) α) (v : Fin (readoutWidth R p) Bool) : Option α := if (decodeStateAt R p dec (readoutWidth R p) 2 v).live && (decodeStateAt R p dec (readoutWidth R p) 2 v).buf.isEmpty && (decodeStateAt R p dec (readoutWidth R p) 2 v).stack.length == 1 then (decodeStateAt R p dec (readoutWidth R p) 2 v).stack.head? else none

The readout as an expression of arity one: a dispatch on the verdict window whose every branch is a constant word.

def readOf (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) : COf 1 := diagOf (casesOf (readoutWidth R p) fun v constAtOf 1 (outWord enc (readState R p dec v)))

The readout's value at the state it reads.

theorem stepWord_readOf (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (u : List Bool) : stepWord (readOf R p enc dec) u = outWord enc (readState R p dec (bits (readoutWidth R p) u)) := α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αu:List BoolstepWord (readOf R p enc dec) u = outWord enc (readState R p dec (bits (readoutWidth R p) u)) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αu:List BoolsemAt 2 (casesOf (readoutWidth R p) fun v constAtOf 1 (outWord enc (readState R p dec v))) ![u, u] = outWord enc (readState R p dec (bits (readoutWidth R p) u)) α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αu:List BoolcasesSem (readoutWidth R p) (fun v constAtOf 1 (outWord enc (readState R p dec v))) ![u, u] = outWord enc (readState R p dec (bits (readoutWidth R p) u)) All goals completed! 🐙

The readout at the state word of a fold scan is the fold's Option. The decoder truncates the stack at two entries, which leaves all three tests unchanged: the marker of the second entry is what separates a stack of one from a longer one.

theorem readState_stateWordF (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (s : FoldScan α) (h : s.buf.length < R.width) : readState R p dec (bits (readoutWidth R p) (stateWordF R enc s)) = (if s.live && s.buf.isEmpty && s.stack.length == 1 then s.stack.head? else none) := α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthreadState R p dec (bits (readoutWidth R p) (stateWordF R enc s)) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }readState R p dec (bits (readoutWidth R p) (stateWordF R enc s)) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }(if ({ buf := s.buf, stack := List.take 2 s.stack, live := s.live }.live && { buf := s.buf, stack := List.take 2 s.stack, live := s.live }.buf.isEmpty && { buf := s.buf, stack := List.take 2 s.stack, live := s.live }.stack.length == 1) = true then { buf := s.buf, stack := List.take 2 s.stack, live := s.live }.stack.head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.length(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:s.stack.length = 1(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else noneα:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:¬s.stack.length = 1(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:s.stack.length = 1(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:s.stack.length = 1h2:(List.take 2 s.stack).length = 1(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:s.stack.length = 1h2:(List.take 2 s.stack).length = 1hhead:(List.take 2 s.stack).head? = s.stack.head?(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none All goals completed! 🐙 α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:¬s.stack.length = 1(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:¬s.stack.length = 1h2:¬(List.take 2 s.stack).length = 1(if (s.live && s.buf.isEmpty && (List.take 2 s.stack).length == 1) = true then (List.take 2 s.stack).head? else none) = if (s.live && s.buf.isEmpty && s.stack.length == 1) = true then s.stack.head? else none α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = as:FoldScan αh:s.buf.length < R.widthhdecode:decodeStateAt R p dec (readoutWidth R p) 2 (bits (readoutWidth R p) (stateWordF R enc s)) = { buf := s.buf, stack := List.take 2 s.stack, live := s.live }hlen:(List.take 2 s.stack).length = min 2 s.stack.lengthhone:¬s.stack.length = 1h2:¬(List.take 2 s.stack).length = 1(if false = true then (List.take 2 s.stack).head? else none) = if false = true then s.stack.head? else none All goals completed! 🐙

The readout composed onto the scan, at its declared arity.

def foldOutOf (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) : COf 1 := comp1Of (readOf R p enc dec) (foldExprOfF R p enc dec hdec alg mult hmult)

The fold as an expression of Cobham's class: the value of a bitstring's term, spelled, and the absent value at a bitstring spelling no term.

def foldOutExpr (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) : C := (foldOutOf R p enc dec hdec alg mult hmult).1

The fold's meaning at its arity, read at the raw tree.

def foldOutSem (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) : Sem 1 := semAt 1 (foldOutOf R p enc dec hdec alg mult hmult).1.1 (foldOutOf R p enc dec hdec alg mult hmult).2

The meaning foldOutSem reads at the raw tree is the meaning foldOutExpr carries.

theorem foldOutSem_eq_eval (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) : transport (foldOutOf R p enc dec hdec alg mult hmult).2 (foldOutOf R p enc dec hdec alg mult hmult).1.eval = foldOutSem R p enc dec hdec alg mult hmult := rfl

One step of the fold: the readout on the scan's value.

theorem foldOutSem_apply (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) (w : List Bool) : foldOutSem R p enc dec hdec alg mult hmult ![w] = stepWord (readOf R p enc dec) (foldSemF R p enc dec alg mult ![w]) := congrArg (semAt 1 (readOf R p enc dec).1.1 (readOf R p enc dec).2) (funext fun i match i with | 0, _ => rfl)

The expression computes the fold: at a bitstring spelling a term, the marked encoding of that term's value under the algebra, and at every other bitstring the absent value.

theorem foldOutSem_eq (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) (w : List Bool) : foldOutSem R p enc dec hdec alg mult hmult ![w] = outWord enc (foldOut R alg w) := α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List BoolfoldOutSem R p enc dec hdec alg mult hmult ![w] = outWord enc (foldOut R alg w) All goals completed! 🐙

The expression computes the decoding followed by the fold: the unique algebra morphism out of the term algebra, read off a preorder spelling.

theorem foldOutSem_eq_parse (R : RankedAlphabet) (p : ) (enc : α Fin p Bool) (dec : (Fin p Bool) α) (hdec : a, dec (enc a) = a) (alg : (i : Fin R.card) (Fin (R.arity i) α) α) (mult : ) (hmult : p + 1 mult * R.width) (w : List Bool) : foldOutSem R p enc dec hdec alg mult hmult ![w] = outWord enc ((R.parse w).map (Term.fold R alg)) := α:Type uR:RankedAlphabetp:enc:α Fin p Booldec:(Fin p Bool) αhdec: (a : α), dec (enc a) = aalg:(i : Fin R.card) (Fin (R.arity i) α) αmult:hmult:p + 1 mult * R.widthw:List BoolfoldOutSem R p enc dec hdec alg mult hmult ![w] = outWord enc (Option.map (Term.fold R alg) (R.parse w)) All goals completed! 🐙
end Geb.CobhamFoldend