Martin Escardo, Paulo Oliva, 2-27 July 2021 We represent the moves of a history-dependent sequential game by a dependent-type tree, collected in a type π». This is either an empty tree [] or else has a type X of initial moves at the root, and, inductively, a family Xf of subtrees indexed by elements of X, which is written X β· Xf. We refer to the family Xf as a forest. We let Xt range over such trees. * Xt ranges over dependent-type trees. * Xf ranges over dependent-type forests. \begin{code} {-# OPTIONS --safe --without-K #-} module Games.TypeTrees where open import Games.Monad open import MLTT.Spartan open import UF.FunExt open import UF.Subsingletons open import UF.Subsingletons-FunExt data π» : Typeβ where [] : π» _β·_ : (X : Type) (Xf : X β π») β π» \end{code} The type of full paths in a tree Xt, from the root to a leaf, is inductively defined as follows: \begin{code} Path : π» β Type Path [] = π Path (X β· Xf) = Ξ£ x κ X , Path (Xf x) \end{code} As discussed above, a play in a game is defined to be such a path. The idea is that we choose a move x, and then, inductively, a path in the subtree Xf x. The variable xs ranges over paths, that is, elements of the type Path Xt for a dependent-type-tree Xt. \begin{code} pattern β¨β© = β pattern _::_ x xs = (x , xs) path-head : {X : Type} {Xf : X β π»} β Path (X β· Xf) β X path-head (x :: xs) = x path-tail : {X : Type} {Xf : X β π»} ((x :: xs) : Path (X β· Xf)) β Path (Xf x) path-tail (x :: xs) = xs plength : {Xt : π»} β Path Xt β β plength {[]} β¨β© = 0 plength {X β· Xf} (x :: xs) = succ (plength {Xf x} xs) subpred : {X R : Type} {Xf : X β π»} β ((Ξ£ x κ X , Path (Xf x)) β R) β (x : X) β Path (Xf x) β R subpred q x xs = q (x :: xs) \end{code} NB. An alternative inductive definition of Path is the following, where, unfortunately, we get a higher type level, and so we won't use it: \begin{code} data Pathβ : π» β Typeβ where [] : Pathβ [] _β·_ : {X : Type} {Xf : X β π»} (x : X) (xs : Pathβ (Xf x)) β Pathβ (X β· Xf) \end{code} Equip the internal nodes of a type tree with structure: \begin{code} structure : (Type β π€ Μ ) β π» β π€ Μ structure S [] = π structure S (X β· Xf) = S X Γ ((x : X) β structure S (Xf x)) \end{code} NB. An alternative inductive definition of structure is the following, where, unfortunately, we get a higher type level, and so we won't use it: \begin{code} data structureβ (S : Type β π€ Μ ) : π» β π€ βΊ Μ where [] : structureβ S [] _β·_ : {X : Type} {Xf : X β π»} β S X β ((x : X) β structureβ S (Xf x)) β structureβ S (X β· Xf) structure-up : (S : Type β π€ Μ ) (Xt : π») β structure S Xt β structureβ S Xt structure-up S [] β¨β© = [] structure-up S (X β· Xf) (s :: sf) = s β· (Ξ» x β structure-up S (Xf x) (sf x)) structure-down : (S : Type β π€ Μ ) (Xt : π») β structureβ S Xt β structure S Xt structure-down S [] [] = β¨β© structure-down S (X β· Xf) (s β· sf) = s :: (Ξ» x β structure-down S (Xf x) (sf x)) \end{code} Xt is hereditarily P if all its internal nodes satisfy P: \begin{code} _is-hereditarily_ : π» β (Type β Type) β Type [] is-hereditarily P = π (X β· Xf) is-hereditarily P = P X Γ ((x : X) β Xf x is-hereditarily P) being-hereditary-is-prop : Fun-Ext β (P : Type β Type) β ((X : Type) β is-prop (P X)) β (Xt : π») β is-prop (Xt is-hereditarily P) being-hereditary-is-prop fe P P-is-prop-valued [] = π-is-prop being-hereditary-is-prop fe P P-is-prop-valued (X β· Xf) = Γ-is-prop (P-is-prop-valued X) (Ξ -is-prop fe Ξ» x β being-hereditary-is-prop fe P P-is-prop-valued (Xf x)) \end{code} The sequence operator for monads is defined on lists, but here we consider a version on paths of a tree instead: \begin{code} path-sequence : (π£ : Monad) {Xt : π»} β structure (functor π£) Xt β functor π£ (Path Xt) path-sequence π£ {[]} β¨β© = Ξ· π£ β¨β© path-sequence π£ {X β· Xf} (t :: tf) = t β[ π£ ] (Ξ» x β path-sequence π£ {Xf x} (tf x)) \end{code} The induction principle for π» is included for the sake of completeness, but won't be used directly: \begin{code} π»-induction : (P : π» β π€ Μ ) β P [] β ((X : Type) (Xf : X β π») β ((x : X) β P (Xf x)) β P (X β· Xf)) β (Xt : π») β P Xt π»-induction P b f = h where h : (Xt : π») β P Xt h [] = b h (X β· Xf) = f X Xf (Ξ» x β h (Xf x)) π»-recursion : (A : π€ Μ ) β A β ((X : Type) β (X β π») β (X β A) β A) β π» β A π»-recursion A = π»-induction (Ξ» _ β A) π»-iteration : (A : π€ Μ ) β A β ((X : Type) β (X β A) β A) β π» β A π»-iteration A a g = π»-induction (Ξ» _ β A) a (Ξ» X Xf β g X) \end{code} Here are some examples for the sake of illustration: \begin{code} private Path' : π» β Type Path' = π»-iteration Type π (Ξ» X F β Ξ£ x κ X , F x) Path'-[] : Path' [] οΌ π Path'-[] = refl Path'-β· : (X : Type) (Xf : X β π») β Path' (X β· Xf) οΌ (Ξ£ x κ X , Path' (Xf x)) Path'-β· X Xf = refl structure' : (S : Type β π€ Μ ) β π» β π€ Μ structure' {π€} S = π»-iteration (π€ Μ ) π (Ξ» X F β S X Γ ((x : X) β F x)) structure'-[] : (S : Type β π€ Μ ) β structure' S [] οΌ π structure'-[] S = refl structure'-β· : (S : Type β π€ Μ ) (X : Type) (Xf : X β π») β structure' S (X β· Xf) οΌ S X Γ ((x : X) β structure' S (Xf x)) structure'-β· S X Xf = refl \end{code}