Trees #
Unified tree type parameterized by node labels (C) and terminal content (W).
Tree C W — The Y-Model Tree #
N-ary branching with categories on every node. Supports both:
- Compositional interpretation (LF):
interp/evalTreeinComposition/Tree.lean— type-driven, ignores categories - Structural operations (PF): @cite{katzir-2007}
StructOp(substitution, deletion, contraction) inAlternatives/Structural.lean— category-aware
Parameterized by category type C (UD tags, CCG categories, feature
bundles, Unit for unlabeled, ...) and terminal type W.
Instantiations #
Tree Unit String— category-free, for H&K composition. Use convenience constructors.leaf,.bin,.un,.tr,.binder.Tree Cat String— UD-grounded categories, for Katzir structural alternatives.Tree Unit LIToken— bare phrase structure, for Minimalist syntax (categories insideLIToken, not on nodes).
Cat — Default Category System #
Grounded in Universal Dependencies UPOS. Word-level categories via
head : UPOS → Cat, phrasal via proj : UPOS → Cat, plus S and CP.
TreePath and Tree.toTreeOrder #
A TreePath is a list of child indices identifying a subtree position.
The forgetful map Tree.toTreeOrder extracts the dominance partial order
from any Tree C W as a Core.Order.TreeOrder TreePath, making the
B&P command-relation library (Linglib.Core.Order.Command) applicable
to concrete trees regardless of category type.
Default syntactic category system grounded in Universal Dependencies UPOS (@cite{de-marneffe-zeman-2021}).
head pos— word-level (terminal): wraps a UPOS tag directlyproj pos— maximal X-bar projection of a UPOS headS— sentence/clause (not a projection of a single lexical head)CP— complementizer phrase
Phrasal categories are derived systematically: NP = proj .NOUN,
VP = proj .VERB, DP = proj .DET, ConjP = proj .CCONJ, etc.
This is one possible instantiation of Tree's C parameter.
Framework-specific category systems (CCG functors, Minimalist
feature bundles, etc.) can be used instead.
Instances For
Equations
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.head a) (Core.Tree.Cat.head b) = if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.head a) (Core.Tree.Cat.proj a_1) = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.head a) Core.Tree.Cat.S = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.head a) Core.Tree.Cat.CP = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.proj a) (Core.Tree.Cat.head a_1) = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.proj a) (Core.Tree.Cat.proj b) = if h : a = b then h ▸ isTrue ⋯ else isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.proj a) Core.Tree.Cat.S = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq (Core.Tree.Cat.proj a) Core.Tree.Cat.CP = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.S (Core.Tree.Cat.head a) = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.S (Core.Tree.Cat.proj a) = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.S Core.Tree.Cat.S = isTrue ⋯
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.S Core.Tree.Cat.CP = isFalse Core.Tree.instDecidableEqCat.decEq._proof_13
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.CP (Core.Tree.Cat.head a) = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.CP (Core.Tree.Cat.proj a) = isFalse ⋯
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.CP Core.Tree.Cat.S = isFalse Core.Tree.instDecidableEqCat.decEq._proof_16
- Core.Tree.instDecidableEqCat.decEq Core.Tree.Cat.CP Core.Tree.Cat.CP = isTrue ⋯
Instances For
Equations
- One or more equations did not get rendered due to their size.
- Core.Tree.instReprCat.repr Core.Tree.Cat.S prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Core.Tree.Cat.S")).group prec✝
- Core.Tree.instReprCat.repr Core.Tree.Cat.CP prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Core.Tree.Cat.CP")).group prec✝
Instances For
Equations
- Core.Tree.instReprCat = { reprPrec := Core.Tree.instReprCat.repr }
Equations
- Core.Tree.instInhabitedCat = { default := Core.Tree.Cat.S }
Equations
- Core.Tree.instBEqCat = { beq := fun (a b : Core.Tree.Cat) => decide (a = b) }
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Equations
Instances For
Framework-neutral tree, parameterized by node label type C
and terminal word type W.
terminal c w— leaf carrying categorycand wordwnode c cs— internal node with categorycand childrencstrace n c— movement trace with indexnand categorycbind n c body— λ-abstraction with indexn, categoryc, scopebody
The node constructor takes a List of children, subsuming both
binary branching (for Heim & Kratzer composition) and n-ary structure
(for Katzir's deletion operation). Binary nodes are node c [l, r].
trace and bind support Quantifier Raising and variable binding.
Frameworks without movement (CCG, HPSG) simply never construct these.
For category-free trees (C = Unit), use the convenience constructors
leaf, bin, un, tr, binder which hide the Unit parameter.
- terminal {C W : Type} : C → W → Tree C W
- node {C W : Type} : C → List (Tree C W) → Tree C W
- trace {C W : Type} : ℕ → C → Tree C W
- bind {C W : Type} : ℕ → C → Tree C W → Tree C W
Instances For
Equations
- Core.Tree.instReprTree = { reprPrec := Core.Tree.instReprTree.repr }
Equations
Instances For
Equations
- t1.bin t2 = Core.Tree.Tree.node () [t1, t2]
Instances For
Equations
- Core.Tree.Tree.tr n = Core.Tree.Tree.trace n ()
Instances For
Equations
- Core.Tree.Tree.binder n body = Core.Tree.Tree.bind n () body
Instances For
Category label of the root node. Total: every constructor carries
a category (including bind, where it labels the result of PA).
Equations
- (Core.Tree.Tree.terminal a a_1).cat = a
- (Core.Tree.Tree.node a a_1).cat = a
- (Core.Tree.Tree.trace a a_1).cat = a_1
- (Core.Tree.Tree.bind a a_1 a_2).cat = a_1
Instances For
Structural equality for trees (mutual recursion through List).
Equations
- (Core.Tree.Tree.terminal c₁ w₁).beq (Core.Tree.Tree.terminal c₂ w₂) = (c₁ == c₂ && w₁ == w₂)
- (Core.Tree.Tree.node c₁ cs₁).beq (Core.Tree.Tree.node c₂ cs₂) = (c₁ == c₂ && Core.Tree.Tree.beq.beqList cs₁ cs₂)
- (Core.Tree.Tree.trace n₁ c₁).beq (Core.Tree.Tree.trace n₂ c₂) = (n₁ == n₂ && c₁ == c₂)
- (Core.Tree.Tree.bind n₁ c₁ b₁).beq (Core.Tree.Tree.bind n₂ c₂ b₂) = (n₁ == n₂ && c₁ == c₂ && b₁.beq b₂)
- x✝¹.beq x✝ = false
Instances For
Equations
- Core.Tree.Tree.beq.beqList [] [] = true
- Core.Tree.Tree.beq.beqList (a :: as) (b :: bs) = (a.beq b && Core.Tree.Tree.beq.beqList as bs)
- Core.Tree.Tree.beq.beqList a✝¹ a✝ = false
Instances For
Equations
- Core.Tree.Tree.instBEq = { beq := Core.Tree.Tree.beq }
Decidable equality on Tree C W, mutually recursive with the
list-of-trees case. Required because deriving DecidableEq does not
handle the nested List (Tree C W) in node.
Equations
- One or more equations did not get rendered due to their size.
- (Core.Tree.Tree.terminal c₁ w₁).decEq (Core.Tree.Tree.terminal c₂ w₂) = if hc : c₁ = c₂ then if hw : w₁ = w₂ then isTrue ⋯ else isFalse ⋯ else isFalse ⋯
- (Core.Tree.Tree.trace n₁ c₁).decEq (Core.Tree.Tree.trace n₂ c₂) = if hn : n₁ = n₂ then if hc : c₁ = c₂ then isTrue ⋯ else isFalse ⋯ else isFalse ⋯
- (Core.Tree.Tree.terminal a a_1).decEq (Core.Tree.Tree.node a_2 a_3) = isFalse ⋯
- (Core.Tree.Tree.terminal a a_1).decEq (Core.Tree.Tree.trace a_2 a_3) = isFalse ⋯
- (Core.Tree.Tree.terminal a a_1).decEq (Core.Tree.Tree.bind a_2 a_3 a_4) = isFalse ⋯
- (Core.Tree.Tree.node a a_1).decEq (Core.Tree.Tree.terminal a_2 a_3) = isFalse ⋯
- (Core.Tree.Tree.node a a_1).decEq (Core.Tree.Tree.trace a_2 a_3) = isFalse ⋯
- (Core.Tree.Tree.node a a_1).decEq (Core.Tree.Tree.bind a_2 a_3 a_4) = isFalse ⋯
- (Core.Tree.Tree.trace a a_1).decEq (Core.Tree.Tree.terminal a_2 a_3) = isFalse ⋯
- (Core.Tree.Tree.trace a a_1).decEq (Core.Tree.Tree.node a_2 a_3) = isFalse ⋯
- (Core.Tree.Tree.trace a a_1).decEq (Core.Tree.Tree.bind a_2 a_3 a_4) = isFalse ⋯
- (Core.Tree.Tree.bind a a_1 a_2).decEq (Core.Tree.Tree.terminal a_3 a_4) = isFalse ⋯
- (Core.Tree.Tree.bind a a_1 a_2).decEq (Core.Tree.Tree.node a_3 a_4) = isFalse ⋯
- (Core.Tree.Tree.bind a a_1 a_2).decEq (Core.Tree.Tree.trace a_3 a_4) = isFalse ⋯
Instances For
Helper: decidable equality for list of trees.
Equations
- One or more equations did not get rendered due to their size.
- Core.Tree.Tree.decEqList [] [] = isTrue ⋯
- Core.Tree.Tree.decEqList [] (head :: tail) = isFalse ⋯
- Core.Tree.Tree.decEqList (head :: tail) [] = isFalse ⋯
Instances For
Number of nodes in the tree.
Equations
- (Core.Tree.Tree.terminal a a_1).size = 1
- (Core.Tree.Tree.node a a_1).size = 1 + Core.Tree.Tree.size.sizeList a_1
- (Core.Tree.Tree.trace a a_1).size = 1
- (Core.Tree.Tree.bind a a_1 a_2).size = 1 + a_2.size
Instances For
Equations
- Core.Tree.Tree.size.sizeList [] = 0
- Core.Tree.Tree.size.sizeList (t :: ts) = t.size + Core.Tree.Tree.size.sizeList ts
Instances For
Number of word-bearing terminals (leaves) in the tree. Traces and binders contribute 0; internal nodes recurse.
Equations
- (Core.Tree.Tree.terminal a a_1).leafCount = 1
- (Core.Tree.Tree.node a a_1).leafCount = Core.Tree.Tree.leafCount.leafCountList a_1
- (Core.Tree.Tree.trace a a_1).leafCount = 0
- (Core.Tree.Tree.bind a a_1 a_2).leafCount = a_2.leafCount
Instances For
Equations
Instances For
Custom recursor for binary trees over Tree Unit W. The default
induction tactic refuses nested inductives like Tree; this recursor
expands the node-case enumeration so each non-binary arity (0, 1, ≥3
children) gets its own branch, separate from the binary binNode case
that carries inductive hypotheses. With @[elab_as_elim], used as
induction t using Tree.binRec with | term … | binNode … | tr … | bd … | nilNode | singletonNode … | manyNode ….
Equations
- One or more equations did not get rendered due to their size.
- Core.Tree.Tree.binRec term binNode tr bd nilNode singletonNode manyNode (Core.Tree.Tree.terminal PUnit.unit w) = term w
- Core.Tree.Tree.binRec term binNode tr bd nilNode singletonNode manyNode (Core.Tree.Tree.node PUnit.unit []) = nilNode
- Core.Tree.Tree.binRec term binNode tr bd nilNode singletonNode manyNode (Core.Tree.Tree.node PUnit.unit [c]) = singletonNode c
- Core.Tree.Tree.binRec term binNode tr bd nilNode singletonNode manyNode (Core.Tree.Tree.node PUnit.unit (c1 :: c2 :: c3 :: cs)) = manyNode c1 c2 c3 cs
- Core.Tree.Tree.binRec term binNode tr bd nilNode singletonNode manyNode (Core.Tree.Tree.trace n PUnit.unit) = tr n
Instances For
All subtrees including self (pre-order traversal).
Equations
- (Core.Tree.Tree.terminal a a_1).subtrees = [Core.Tree.Tree.terminal a a_1]
- (Core.Tree.Tree.node a cs).subtrees = Core.Tree.Tree.node a cs :: Core.Tree.Tree.subtrees.subtreesList cs
- (Core.Tree.Tree.trace a a_1).subtrees = [Core.Tree.Tree.trace a a_1]
- (Core.Tree.Tree.bind a a_1 body).subtrees = Core.Tree.Tree.bind a a_1 body :: body.subtrees
Instances For
Equations
- Core.Tree.Tree.subtrees.subtreesList [] = []
- Core.Tree.Tree.subtrees.subtreesList (t :: ts) = t.subtrees ++ Core.Tree.Tree.subtrees.subtreesList ts
Instances For
Whether a category appears anywhere in the tree.
Equations
- Core.Tree.Tree.containsCat target (Core.Tree.Tree.terminal a a_1) = (target == a)
- Core.Tree.Tree.containsCat target (Core.Tree.Tree.node a a_1) = (target == a || Core.Tree.Tree.containsCat.containsCatList target a_1)
- Core.Tree.Tree.containsCat target (Core.Tree.Tree.trace a a_1) = (target == a_1)
- Core.Tree.Tree.containsCat target (Core.Tree.Tree.bind a a_1 a_2) = (target == a_1 || Core.Tree.Tree.containsCat target a_2)
Instances For
Equations
- Core.Tree.Tree.containsCat.containsCatList target [] = false
- Core.Tree.Tree.containsCat.containsCatList target (t :: ts) = (Core.Tree.Tree.containsCat target t || Core.Tree.Tree.containsCat.containsCatList target ts)
Instances For
Substitute all terminals of category c carrying word target
with replacement. This is the most common structural operation:
replacing one scalar item with another of the same category.
Equations
- Core.Tree.Tree.leafSubst target replacement c (Core.Tree.Tree.terminal a a_1) = if (c == a && a_1 == target) = true then Core.Tree.Tree.terminal a replacement else Core.Tree.Tree.terminal a a_1
- Core.Tree.Tree.leafSubst target replacement c (Core.Tree.Tree.node a a_1) = Core.Tree.Tree.node a (Core.Tree.Tree.leafSubst.leafSubstList target replacement c a_1)
- Core.Tree.Tree.leafSubst target replacement c (Core.Tree.Tree.trace a a_1) = Core.Tree.Tree.trace a a_1
- Core.Tree.Tree.leafSubst target replacement c (Core.Tree.Tree.bind a a_1 a_2) = Core.Tree.Tree.bind a a_1 (Core.Tree.Tree.leafSubst target replacement c a_2)
Instances For
Equations
- Core.Tree.Tree.leafSubst.leafSubstList target replacement c [] = []
- Core.Tree.Tree.leafSubst.leafSubstList target replacement c (t :: ts) = Core.Tree.Tree.leafSubst target replacement c t :: Core.Tree.Tree.leafSubst.leafSubstList target replacement c ts
Instances For
A path from the root of a tree, encoded as a list of child indices.
Each element is the index in the parent's child list (or 0 for the
unique child of a bind). The empty path identifies the root.
- toList : List ℕ
The underlying list of child indices.
Instances For
Dominance order: p ≤ q iff p is a prefix of q.
Equations
- Core.Tree.TreePath.instLE = { le := fun (p q : Core.Tree.TreePath) => p.toList <+: q.toList }
Equations
- One or more equations did not get rendered due to their size.
Subtree at the given path; none if the path leaves the tree.
For node c cs, the next index i selects child cs[i]?; for
bind, only index 0 is valid (binders have a single body).
Equations
- x✝.subtreeAt [] = some x✝
- (Core.Tree.Tree.node a cs).subtreeAt (i :: rest) = cs[i]?.bind fun (child : Core.Tree.Tree C W) => child.subtreeAt rest
- (Core.Tree.Tree.bind a a_1 body).subtreeAt (0 :: rest) = body.subtreeAt rest
- (Core.Tree.Tree.bind a a_1 a_2).subtreeAt (head :: tail) = none
- (Core.Tree.Tree.terminal a a_1).subtreeAt (head :: tail) = none
- (Core.Tree.Tree.trace a a_1).subtreeAt (head :: tail) = none
Instances For
Set of valid paths in the tree (paths that resolve to a subtree).
Equations
- t.validPaths = {p : Core.Tree.TreePath | (t.subtreeAt p.toList).isSome = true}
Instances For
Forgetful map from a Tree C W to its dominance order as a
TreeOrder TreePath. This makes the framework-agnostic command-
relation library (@cite{barker-pullum-1990}, B&P) directly applicable
to any concrete tree, regardless of category or word type.
Equations
- t.toTreeOrder = { nodes := t.validPaths, root := { toList := [] }, root_in_nodes := ⋯, root_le_all := ⋯, ancestor_connected := ⋯ }
Instances For
Forgetful map from a free magma to a binary Core.Tree.Tree Unit α.
The image lives in a strict subset of Tree Unit α: only .terminal ()
(from .of) and the binary .node () [_, _] (from .mul) are produced;
the n-ary .node, .trace, and .bind constructors are never used.
By composition with Core.Tree.Tree.toTreeOrder, every FreeMagma α
inherits a Core.Order.TreeOrder Core.Tree.TreePath, making B&P's
framework-agnostic command-relation library
(Linglib.Core.Order.Command) directly applicable.
Universe note: capped at α : Type because Core.Tree.Tree is monomorphic
in Type 0; sufficient for LIToken-indexed SyntacticObject.
Equations
- (FreeMagma.of a).toTree = Core.Tree.Tree.terminal () a
- (l.mul r).toTree = Core.Tree.Tree.node () [l.toTree, r.toTree]