Games.TypeTrees
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.{-# OPTIONS --safe --without-K #-} open import MLTT.Spartan module Games.TypeTrees {π€ : Universe} where open import MonadOnTypes.Definition hiding (map) open import UF.FunExt open import UF.Subsingletons open import UF.Subsingletons-FunExt data π» : π€ βΊ Μ where [] : π» _β·_ : (X : π€ Μ ) (Xf : X β π») β π»The type of full paths in a tree Xt, from the root to a leaf, is inductively defined as follows:Path : π» β π€ Μ Path [] = π Path (X β· Xf) = Ξ£ x κ X , Path (Xf x)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.pattern β¨β© = β pattern _::_ x xs = (x , xs) path-head : {X : π€ Μ } {Xf : X β π»} β Path (X β· Xf) β X path-head (x :: xs) = x path-tail : {X : π€ Μ } {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 : π£ Μ } {Xf : X β π»} β ((Ξ£ x κ X , Path (Xf x)) β R) β (x : X) β Path (Xf x) β R subpred q x xs = q (x :: xs)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:data Pathβ : π» β π€ βΊ Μ where [] : Pathβ [] _β·_ : {X : π€ Μ } {Xf : X β π»} (x : X) (xs : Pathβ (Xf x)) β Pathβ (X β· Xf)Equip the internal nodes of a type tree with structure:structure : (π€ Μ β π₯ Μ ) β π» β π€ β π₯ Μ structure S [] = π structure S (X β· Xf) = S X Γ ((x : X) β structure S (Xf x))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:data structureβ (S : π€ Μ β π₯ Μ ) : π» β π€ βΊ β π₯ Μ where [] : structureβ S [] _β·_ : {X : π€ Μ } {Xf : X β π»} β S X β ((x : X) β structureβ S (Xf x)) β structureβ S (X β· Xf) structure-up : (S : π€ Μ β π₯ Μ ) (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 : π€ Μ β π₯ Μ ) (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))Xt is hereditarily P if all its internal nodes satisfy P:_is-hereditarily_ : π» β (π€ Μ β π₯ Μ ) β π€ β π₯ Μ [] is-hereditarily P = π (X β· Xf) is-hereditarily P = P X Γ ((x : X) β Xf x is-hereditarily P) being-hereditary-is-prop : Fun-Ext β (P : π€ Μ β π₯ Μ ) β ((X : π€ Μ ) β 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))The sequence operator for monads is defined on lists, but here we consider a version on paths of a tree instead:path-sequence : {β : Universe β Universe} (π£ : Monad {β}) {Xt : π»} β structure (functor π£) Xt β functor π£ (Path Xt) path-sequence π£ {[]} β¨β© = Ξ· π£ β¨β© path-sequence π£ {X β· Xf} (t :: tf) = t β[ π£ ] (Ξ» x β path-sequence π£ {Xf x} (tf x))The induction principle for π» is included for the sake of completeness, but won't be used directly:π»-induction : (P : π» β π₯ Μ ) β P [] β ((X : π€ Μ ) (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 : π€ Μ ) β (X β π») β (X β A) β A) β π» β A π»-recursion A = π»-induction (Ξ» _ β A) π»-iteration : (A : π₯ Μ ) β A β ((X : π€ Μ ) β (X β A) β A) β π» β A π»-iteration A a g = π»-induction (Ξ» _ β A) a (Ξ» X Xf β g X)Here are some examples for the sake of illustration:private Path' : π» β π€ Μ Path' = π»-iteration (_ Μ ) π (Ξ» X F β Ξ£ x κ X , F x) Path'-[] : Path' [] οΌ π Path'-[] = refl Path'-β· : (X : π€ Μ ) (Xf : X β π») β Path' (X β· Xf) οΌ (Ξ£ x κ X , Path' (Xf x)) Path'-β· X Xf = refl structure' : (S : π€ Μ β π₯ Μ ) β π» β π€ β π₯ Μ structure' {π₯} S = π»-iteration (π€ β π₯ Μ ) π (Ξ» X F β S X Γ ((x : X) β F x)) structure'-[] : (S : π€ Μ β π₯ Μ ) β structure' S [] οΌ π structure'-[] S = refl structure'-β· : (S : π€ Μ β π₯ Μ ) (X : π€ Μ ) (Xf : X β π») β structure' S (X β· Xf) οΌ S X Γ ((x : X) β structure' S (Xf x)) structure'-β· S X Xf = reflMoved here 22 Oct 2025 from code from 8th October 2025 in the file OptimalPlays, with a simplification on 29th October.open import MLTT.List private Ξ½ : {X : π€ Μ } {Xf : X β π»} β ((x : X) β List (Path (Xf x))) β (X β List (Path (X β· Xf))) Ξ½ f x = map (x ::_) (f x)Notice that the above function Ξ½ transforms a dependent function into a non-dependent one.list-of-all-paths : (Xt : π») (lt : structure listed Xt) β List (Path Xt) list-of-all-paths [] β¨β© = [ β¨β© ] list-of-all-paths (X β· Xf) ((xs , m) , lf) = List-ext (Ξ½ f) xs where f : (x : X) β List (Path (Xf x)) f x = list-of-all-paths (Xf x) (lf x) path-is-member-of-list-of-all-paths : (Xt : π») (lt : structure listed Xt) (xs : Path Xt) β member xs (list-of-all-paths Xt lt) path-is-member-of-list-of-all-paths [] β¨β© β¨β© = in-head path-is-member-of-list-of-all-paths (X β· Xf) ((ys , m) , lf) (x :: xs) = III where f : (x : X) β List (Path (Xf x)) f x = list-of-all-paths (Xf x) (lf x) IH : member xs (f x) IH = path-is-member-of-list-of-all-paths (Xf x) (lf x) xs I : member (x :: xs) (Ξ½ f x) I = member-of-mapβ (x ::_) (f x) xs IH II : member (Ξ½ f x) (map (Ξ½ f) ys) II = member-of-mapβ (Ξ½ f) ys x (m x) III : member (x :: xs) (List-ext (Ξ½ f) ys) III = member-of-concatβ (x :: xs) (map (Ξ½ f) ys) (Ξ½ f x) II IWe are not currently using pmap, but we keep it for the record:pmap : {X : π€ Μ } {Xf : X β π»} β ((x : X) β Path (Xf x)) β List X β List (Path (X β· Xf)) pmap = dmap