M-types #
M types are potentially infinite tree-like structures. They are defined as the greatest fixpoint of a polynomial functor.
CofixA F n
is an n
level approximation of an M-type
- continue: {F : PFunctor.{u}} → PFunctor.Approx.CofixA F 0
- intro: {F : PFunctor.{u}} → {n : ℕ} → (a : F.A) → (F.B a → PFunctor.Approx.CofixA F n) → PFunctor.Approx.CofixA F (Nat.succ n)
Instances For
default inhabitant of CofixA
Equations
- PFunctor.Approx.CofixA.default F 0 = PFunctor.Approx.CofixA.continue
- PFunctor.Approx.CofixA.default F (Nat.succ n) = PFunctor.Approx.CofixA.intro default fun (x : F.B default) => PFunctor.Approx.CofixA.default F n
Instances For
Equations
- PFunctor.Approx.instInhabitedCofixA F = { default := PFunctor.Approx.CofixA.default F n }
The label of the root of the tree for a non-trivial approximation of the cofix of a pfunctor.
Equations
- PFunctor.Approx.head' x = match x✝, x with | x, PFunctor.Approx.CofixA.intro i a => i
Instances For
for a non-trivial approximation, return all the subtrees of the root
Equations
- One or more equations did not get rendered due to their size.
Instances For
Relation between two approximations of the cofix of a pfunctor that state they both contain the same data until one of them is truncated
- continu: ∀ {F : PFunctor.{u}} (x : PFunctor.Approx.CofixA F 0) (y : PFunctor.Approx.CofixA F 1), PFunctor.Approx.Agree x y
- intro: ∀ {F : PFunctor.{u}} {n : ℕ} {a : F.A} (x : F.B a → PFunctor.Approx.CofixA F n) (x' : F.B a → PFunctor.Approx.CofixA F (n + 1)), (∀ (i : F.B a), PFunctor.Approx.Agree (x i) (x' i)) → PFunctor.Approx.Agree (PFunctor.Approx.CofixA.intro a x) (PFunctor.Approx.CofixA.intro a x')
Instances For
Given an infinite series of approximations approx
,
AllAgree approx
states that they are all consistent with each other.
Equations
- PFunctor.Approx.AllAgree x = ∀ (n : ℕ), PFunctor.Approx.Agree (x n) (x (Nat.succ n))
Instances For
truncate a
turns a
into a more limited approximation
Equations
- PFunctor.Approx.truncate (PFunctor.Approx.CofixA.intro a a_1) = PFunctor.Approx.CofixA.continue
- PFunctor.Approx.truncate (PFunctor.Approx.CofixA.intro i f) = PFunctor.Approx.CofixA.intro i (PFunctor.Approx.truncate ∘ f)
Instances For
sCorec f i n
creates an approximation of height n
of the final coalgebra of f
Equations
- PFunctor.Approx.sCorec f x 0 = PFunctor.Approx.CofixA.continue
- PFunctor.Approx.sCorec f x (Nat.succ n) = PFunctor.Approx.CofixA.intro (f x).fst fun (i : F.B (f x).fst) => PFunctor.Approx.sCorec f ((f x).snd i) n
Instances For
Equations
- PFunctor.Approx.Path.inhabited = { default := [] }
Equations
- (_ : Subsingleton (PFunctor.Approx.CofixA F 0)) = (_ : Subsingleton (PFunctor.Approx.CofixA F 0))
Internal definition for M
. It is needed to avoid name clashes
between M.mk
and M.cases_on
and the declarations generated for
the structure
- approx : (n : ℕ) → PFunctor.Approx.CofixA F n
An
n
-th level approximation, for each depthn
- consistent : PFunctor.Approx.AllAgree self.approx
Each approximation agrees with the next
Instances For
Equations
- PFunctor.M.inhabited F = { default := { approx := default, consistent := (_ : ∀ (n : ℕ), PFunctor.Approx.Agree default default) } }
Equations
- PFunctor.MIntl.inhabited F = let_fun this := inferInstance; this
Corecursor for the M-type defined by F
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
given a tree generated by F
, head
gives us the first piece of data
it contains
Equations
- PFunctor.M.head x = PFunctor.Approx.head' (x.approx 1)
Instances For
return all the subtrees of the root of a tree x : M F
Equations
- One or more equations did not get rendered due to their size.
Instances For
select a subtree using an i : F.Idx
or return an arbitrary tree if
i
designates no subtree of x
Equations
- PFunctor.M.ichildren i x = if H' : i.fst = PFunctor.M.head x then PFunctor.M.children x (cast (_ : F.B i.fst = F.B (PFunctor.M.head x)) i.snd) else default
Instances For
unfold an M-type
Equations
- PFunctor.M.dest x = let x := x; { fst := PFunctor.M.head x, snd := fun (i : F.B (PFunctor.M.head x)) => PFunctor.M.children x i }
Instances For
generates the approximations needed for M.mk
Equations
- PFunctor.M.Approx.sMk x✝ x = match x with | 0 => PFunctor.Approx.CofixA.continue | Nat.succ n => PFunctor.Approx.CofixA.intro x✝.fst fun (i : F.B x✝.fst) => (x✝.snd i).approx n
Instances For
constructor for M-types
Equations
- PFunctor.M.mk x = { approx := PFunctor.M.Approx.sMk x, consistent := (_ : PFunctor.Approx.AllAgree (PFunctor.M.Approx.sMk x)) }
Instances For
Agree' n
relates two trees of type M F
that
are the same up to depth n
- trivial: ∀ {F : PFunctor.{u}} (x y : PFunctor.M F), PFunctor.M.Agree' 0 x y
- step: ∀ {F : PFunctor.{u}} {n : ℕ} {a : F.A} (x y : F.B a → PFunctor.M F) {x' y' : PFunctor.M F}, x' = PFunctor.M.mk { fst := a, snd := x } → y' = PFunctor.M.mk { fst := a, snd := y } → (∀ (i : F.B a), PFunctor.M.Agree' n (x i) (y i)) → PFunctor.M.Agree' (Nat.succ n) x' y'
Instances For
destructor for M-types
Equations
- PFunctor.M.cases f x = let_fun this := f (PFunctor.M.dest x); Eq.mpr (_ : r x = r (PFunctor.M.mk (PFunctor.M.dest x))) this
Instances For
destructor for M-types
Equations
- PFunctor.M.casesOn x f = PFunctor.M.cases f x
Instances For
destructor for M-types, similar to casesOn
but also
gives access directly to the root and subtrees on an M-type
Equations
- PFunctor.M.casesOn' x f = PFunctor.M.casesOn x fun (x : ↑F (PFunctor.M F)) => match x with | { fst := a, snd := g } => f a g
Instances For
IsPath p x
tells us if p
is a valid path through x
- nil: ∀ {F : PFunctor.{u}} (x : PFunctor.M F), PFunctor.M.IsPath [] x
- cons: ∀ {F : PFunctor.{u}} (xs : PFunctor.Approx.Path F) {a : F.A} (x : PFunctor.M F) (f : F.B a → PFunctor.M F) (i : F.B a), x = PFunctor.M.mk { fst := a, snd := f } → PFunctor.M.IsPath xs (f i) → PFunctor.M.IsPath ({ fst := a, snd := i } :: xs) x
Instances For
follow a path through a value of M F
and return the subtree
found at the end of the path if it is a valid path for that value and
return a default tree
Equations
- One or more equations did not get rendered due to their size.
- PFunctor.M.isubtree [] x = x
Instances For
similar to isubtree
but returns the data at the end of the path instead
of the whole subtree
Equations
- PFunctor.M.iselect ps x = PFunctor.M.head (PFunctor.M.isubtree ps x)
Instances For
Bisimulation is the standard proof technique for equality between infinite tree-like structures
- head : ∀ {a a' : F.A} {f : F.B a → PFunctor.M F} {f' : F.B a' → PFunctor.M F}, R (PFunctor.M.mk { fst := a, snd := f }) (PFunctor.M.mk { fst := a', snd := f' }) → a = a'
The head of the trees are equal
- tail : ∀ {a : F.A} {f f' : F.B a → PFunctor.M F}, R (PFunctor.M.mk { fst := a, snd := f }) (PFunctor.M.mk { fst := a, snd := f' }) → ∀ (i : F.B a), R (f i) (f' i)
The tails are equal
Instances For
corecursor for M F
with swapped arguments
Equations
- PFunctor.M.corecOn x₀ f = PFunctor.M.corec f x₀
Instances For
corecursor where the state of the computation can be sent downstream in the form of a recursive call
Equations
- PFunctor.M.corec₁ F = PFunctor.M.corec (F α id)
Instances For
corecursor where it is possible to return a fully formed value at any point of the computation
Equations
- One or more equations did not get rendered due to their size.