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 n.succ
Instances For
default inhabitant of CofixA
Equations
- PFunctor.Approx.CofixA.default F 0 = PFunctor.Approx.CofixA.continue
- PFunctor.Approx.CofixA.default F n.succ = PFunctor.Approx.CofixA.intro default fun (x : F.B default) => PFunctor.Approx.CofixA.default F n
Instances For
Equations
- PFunctor.Approx.instInhabitedCofixAOfA 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
Instances For
for a non-trivial approximation, return all the subtrees of the root
Equations
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 n.succ)
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✝ n.succ = 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
Path F
provides indices to access internal nodes in Corec F
Equations
- PFunctor.Approx.Path F = List F.Idx
Instances For
Equations
- PFunctor.Approx.Path.inhabited = { default := [] }
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 := ⋯ } }
Equations
- PFunctor.MIntl.inhabited F = inferInstance
Corecursor for the M-type defined by F
.
Equations
- PFunctor.M.corec f i = { approx := PFunctor.Approx.sCorec f i, consistent := ⋯ }
Instances For
given a tree generated by F
, head
gives us the first piece of data
it contains
Equations
- x.head = PFunctor.Approx.head' (x.approx 1)
Instances For
return all the subtrees of the root of a tree x : M F
Equations
- x.children i = { approx := fun (n : ℕ) => PFunctor.Approx.children' (x.approx n.succ) (cast ⋯ i), consistent := ⋯ }
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 = x.head then x.children (cast ⋯ i.snd) else default
Instances For
generates the approximations needed for M.mk
Equations
- PFunctor.M.Approx.sMk x 0 = PFunctor.Approx.CofixA.continue
- PFunctor.M.Approx.sMk x n.succ = 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 := ⋯ }
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 : F.M) : PFunctor.M.Agree' 0 x y
- step {F : PFunctor.{u}} {n : ℕ} {a : F.A} (x y : F.B a → F.M) {x' y' : F.M} : x' = PFunctor.M.mk ⟨a, x⟩ → y' = PFunctor.M.mk ⟨a, y⟩ → (∀ (i : F.B a), PFunctor.M.Agree' n (x i) (y i)) → PFunctor.M.Agree' n.succ x' y'
Instances For
destructor for M-types
Equations
- PFunctor.M.cases f x = ⋯.mpr (f x.dest)
Instances For
destructor for M-types
Equations
- x.casesOn 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
- x.casesOn' f = x.casesOn fun (x : ↑F F.M) => match x with | ⟨a, g⟩ => f a g
Instances For
IsPath p x
tells us if p
is a valid path through x
- nil {F : PFunctor.{u}} (x : F.M) : PFunctor.M.IsPath [] x
- cons {F : PFunctor.{u}} (xs : PFunctor.Approx.Path F) {a : F.A} (x : F.M) (f : F.B a → F.M) (i : F.B a) : x = PFunctor.M.mk ⟨a, f⟩ → PFunctor.M.IsPath xs (f i) → PFunctor.M.IsPath (⟨a, 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
- PFunctor.M.isubtree [] x✝ = x✝
- PFunctor.M.isubtree (⟨a, i⟩ :: ps) x✝ = x✝.casesOn' fun (a' : F.A) (f : F.B a' → F.M) => if h : a = a' then PFunctor.M.isubtree ps (f (cast ⋯ i)) else default
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.isubtree ps x).head
Instances For
Bisimulation is the standard proof technique for equality between infinite tree-like structures
- head {a a' : F.A} {f : F.B a → F.M} {f' : F.B a' → F.M} : R (PFunctor.M.mk ⟨a, f⟩) (PFunctor.M.mk ⟨a', f'⟩) → a = a'
The head of the trees are equal
- tail {a : F.A} {f f' : F.B a → F.M} : R (PFunctor.M.mk ⟨a, f⟩) (PFunctor.M.mk ⟨a, 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.