---
layout: default
title : "Legacy.Base.Terms.Operations module (The Agda Universal Algebra Library)"
date : "2021-01-14"
author: "agda-algebras development team"
---

### <a id="term-operations">Term Operations</a>

This section presents the [Legacy.Base.Terms.Operations][] module of the [Agda Universal Algebra Library][].

Here we define *term operations* which are simply terms interpreted in a
particular algebra, and we prove some compatibility properties of term operations.


```agda


{-# OPTIONS --cubical-compatible --exact-split --safe #-}

open import Overture using ( š“ž ; š“„ ; Signature )

module Legacy.Base.Terms.Operations {š‘† : Signature š“ž š“„} where

-- Imports from Agda and the Agda Standard Library ---------------------
open import Agda.Primitive  using ()  renaming ( Set to Type )
open import Data.Product    using ( _,_ ; Σ-syntax ; Σ )
open import Function        using ( _∘_ )
open import Level           using ( Level ; _āŠ”_ )
open import Relation.Binary.PropositionalEquality as ≔
                            using ( _≔_ ; module ≔-Reasoning )
open import Axiom.Extensionality.Propositional
                            using () renaming (Extensionality to funext)

-- Imports from Agda Universal Algebra Library ----------------------------------------------
open import Overture        using ( _āˆ™_ ; _⁻¹ ; ∣_∣ ; ∄_∄ ; Ī  ; Ī -syntax ; _ā‰ˆ_ )
open import Legacy.Base.Relations  using ( _|:_ )
open import Legacy.Base.Equality   using ( swelldef )

open import Legacy.Base.Algebras          {š‘† = š‘†}  using ( Algebra ; _Ģ‚_ ; ov ; ⨅ )
                                            using ( IsCongruence ; Con )
open import Legacy.Base.Homomorphisms     {š‘† = š‘†}  using ( hom )
open import Legacy.Base.Terms.Basic       {š‘† = š‘†}  using ( Term ; š‘» )
open import Legacy.Base.Terms.Properties  {š‘† = š‘†}  using ( free-lift )

open Term
private variable α β γ ρ χ : Level
```


When we interpret a term in an algebra we call the resulting function a
*term operation*. Given a term `p` and an algebra `š‘Ø`, we denote by `š‘Ø ⟦ p ⟧`
the *interpretation* of `p` in `š‘Ø`.  This is defined inductively as follows.

1.  If `p` is a variable symbol `x : X` and if `a : X → ∣ š‘Ø ∣` is a tuple of
    elements of `∣ š‘Ø ∣`, then `š‘Ø ⟦ p ⟧ a := a x`.

2.  If `p = f t`, where `f : ∣ š‘† ∣` is an operation symbol, if `t : ∄ š‘† ∄ f → š‘» X`
    is a tuple of terms, and if `a : X → ∣ š‘Ø ∣` is a tuple from `š‘Ø`, then we
    define `š‘Ø ⟦ p ⟧ a = š‘Ø ⟦ f t ⟧ a := (f Ģ‚ š‘Ø) (Ī» i → š‘Ø ⟦ t i ⟧ a)`.

Thus the interpretation of a term is defined by induction on the structure of the
term, and the definition is formally implemented in the [agda-algebras][]
library as follows.


```agda


_⟦_⟧ : (š‘Ø : Algebra α){X : Type χ } → Term X → (X → ∣ š‘Ø ∣) → ∣ š‘Ø ∣
š‘Ø ⟦ ā„Š x ⟧ = Ī» Ī· → Ī· x
š‘Ø ⟦ node f t ⟧ = Ī» Ī· → (f Ģ‚ š‘Ø) (Ī» i → (š‘Ø ⟦ t i ⟧) Ī·)
```


It turns out that the intepretation of a term is the same as the `free-lift`
(modulo argument order and assuming function extensionality).


```agda


free-lift-interp :  swelldef š“„ α → (š‘Ø : Algebra α){X : Type χ }
                    (Ī· : X → ∣ š‘Ø ∣)(p : Term X) → (š‘Ø ⟦ p ⟧) Ī· ≔ (free-lift š‘Ø Ī·) p

free-lift-interp _ š‘Ø Ī· (ā„Š x) = ≔.refl
free-lift-interp wd š‘Ø Ī· (node f t) =
 wd (f Ģ‚ š‘Ø) (Ī» z → (š‘Ø ⟦ t z ⟧) Ī·)
 ((free-lift š‘Ø Ī·) ∘ t)((free-lift-interp wd š‘Ø Ī·) ∘ t)
```


If the algebra in question happens to be `š‘» X`, then we expect that `āˆ€ s`
we have `(š‘» X)⟦ p ⟧ s ≔ p s`. But what is `(š‘» X)⟦ p ⟧ s` exactly? By
definition, it depends on the form of `p` as follows:

*  if `p = ā„Š x`, then `(š‘» X)⟦ p ⟧ s := (š‘» X)⟦ ā„Š x ⟧ s ≔ s x`

*  if `p = node f t`, then
   `(š‘» X)⟦ p ⟧ s := (š‘» X)⟦ node f t ⟧ s = (f Ģ‚ š‘» X) Ī» i → (š‘» X)⟦ t i ⟧ s`

Now, assume `Ļ• : hom š‘» š‘Ø`. Then by `comm-hom-term`, we have
`∣ Ļ• ∣ (š‘» X)⟦ p ⟧ s = š‘Ø ⟦ p ⟧ ∣ Ļ• ∣ ∘ s`.

* if `p = ā„Š x` (and `t : X → ∣ š‘» X ∣`), then

  `∣ Ļ• ∣ p ≔ ∣ Ļ• ∣ (ā„Š x) ≔ ∣ Ļ• ∣ (Ī» t → h t) ≔ Ī» t → (∣ Ļ• ∣ ∘ t) x`

* if `p = node f t`, then

   `∣ Ļ• ∣ p ≔ ∣ Ļ• ∣ (š‘» X)⟦ p ⟧ s = (š‘» X)⟦ node f t ⟧ s = (f Ģ‚ š‘» X) Ī» i → (š‘» X)⟦ t i ⟧ s`

We claim that for all `p : Term X` there exists `q : Term X` and `t : X → ∣ š‘» X ∣`
such that `p ≔ (š‘» X)⟦ q ⟧ t`. We prove this fact as follows.


```agda


term-interp :  {X : Type χ} (f : ∣ š‘† ∣){s t : ∄ š‘† ∄ f → Term X}
 →             s ≔ t → node f s ≔ (f Ģ‚ š‘» X) t

term-interp f {s}{t} st = ≔.cong (node f) st


term-interp' :  swelldef š“„ (ov χ) → {X : Type χ} (f : ∣ š‘† ∣){s t : ∄ š‘† ∄ f → Term X}
 →              (āˆ€ i → s i ≔ t i) → node f s ≔ (f Ģ‚ š‘» X) t

term-interp' wd f {s}{t} st = wd (node f) s t st


term-gen :  swelldef š“„ (ov χ) → {X : Type χ}(p : ∣ š‘» X ∣)
 →          Ī£[ q ∈ ∣ š‘» X ∣ ] p ≔ (š‘» X ⟦ q ⟧) ā„Š

term-gen _ (ā„Š x) = (ā„Š x) , ≔.refl
term-gen wd (node f t) =  (node f (Ī» i → ∣ term-gen wd (t i) ∣)) ,
                          term-interp' wd f Ī» i → ∄ term-gen wd (t i) ∄

term-gen-agreement :  (wd : swelldef š“„ (ov χ)){X : Type χ}(p : ∣ š‘» X ∣)
 →                    (š‘» X ⟦ p ⟧) ā„Š ≔ (š‘» X ⟦ ∣ term-gen wd p ∣ ⟧) ā„Š
term-gen-agreement _ (ā„Š x) = ≔.refl
term-gen-agreement wd {X} (node f t) = wd  ( f Ģ‚ š‘» X) (Ī» x → (š‘» X ⟦ t x ⟧) ā„Š)
                                           (Ī» x → (š‘» X ⟦ ∣ term-gen wd (t x) ∣ ⟧) ā„Š)
                                           Ī» i → term-gen-agreement wd (t i)

term-agreement : swelldef š“„ (ov χ) → {X : Type χ}(p : ∣ š‘» X ∣) → p ≔  (š‘» X ⟦ p ⟧) ā„Š
term-agreement wd {X} p = ∄ term-gen wd p ∄ āˆ™ (term-gen-agreement wd p)⁻¹
```



#### <a id="interpretation-of-terms-in-product-algebras">Interpretation of terms in product algebras</a>


```agda


module _ (wd : swelldef š“„ (β āŠ” α)){X : Type χ }{I : Type β} where

 interp-prod :  (p : Term X)(š’œ : I → Algebra α)(a : X → Ī [ i ∈ I ] ∣ š’œ i ∣)
  →             (⨅ š’œ ⟦ p ⟧) a ≔ Ī» i → (š’œ i ⟦ p ⟧)(Ī» x → (a x) i)

 interp-prod (ā„Š _) š’œ a = ≔.refl
 interp-prod (node f t) š’œ a = wd ((f Ģ‚ ⨅ š’œ)) u v IH
  where
  u : āˆ€ x → ∣ ⨅ š’œ ∣
  u = Ī» x → (⨅ š’œ ⟦ t x ⟧) a
  v : āˆ€ x i → ∣ š’œ i ∣
  v = Ī» x i → (š’œ i ⟦ t x ⟧)(Ī» j → a j i)
  IH : āˆ€ i → u i ≔ v i
  IH = Ī» x → interp-prod (t x) š’œ a

 interp-prod2 :  funext (α āŠ” β āŠ” χ) (α āŠ” β) → (p : Term X)(š’œ : I → Algebra α)
  →              ⨅ š’œ ⟦ p ⟧ ≔ (Ī» a i → (š’œ i ⟦ p ⟧) Ī» x → a x i)

 interp-prod2 _ (ā„Š x₁) š’œ = ≔.refl
 interp-prod2 fe (node f t) š’œ = fe Ī» a → wd (f Ģ‚ ⨅ š’œ)(u a) (v a) (IH a)
  where
  u : āˆ€ a x → ∣ ⨅ š’œ ∣
  u a = Ī» x → (⨅ š’œ ⟦ t x ⟧) a
  v : āˆ€ (a : X → ∣ ⨅ š’œ ∣) → āˆ€ x i → ∣ š’œ i ∣
  v a = Ī» x i → (š’œ i ⟦ t x ⟧)(Ī» z → (a z) i)
  IH : āˆ€ a x → (⨅ š’œ ⟦ t x ⟧) a ≔ Ī» i → (š’œ i ⟦ t x ⟧)(Ī» z → (a z) i)
  IH a = Ī» x → interp-prod (t x) š’œ a
```



#### <a id="compatibility-of-terms">Compatibility of terms</a>

We now prove two important facts about term operations.  The first of these, which
is used very often in the sequel, asserts that every term commutes with every
homomorphism.


```agda


open ≔-Reasoning

comm-hom-term :  swelldef š“„ β → {š‘Ø : Algebra α} (š‘© : Algebra β)
                 (h : hom š‘Ø š‘©){X : Type χ}(t : Term X)(a : X → ∣ š‘Ø ∣)
                 ------------------------------------------------------
  →              ∣ h ∣ ((š‘Ø ⟦ t ⟧) a) ≔ (š‘© ⟦ t ⟧) (∣ h ∣ ∘ a)

comm-hom-term _ š‘© h (ā„Š x) a = ≔.refl
comm-hom-term wd {š‘Ø} š‘© h (node f t) a =
 ∣ h ∣((f Ģ‚ š‘Ø) Ī» i →  (š‘Ø ⟦ t i ⟧) a)      ā‰”āŸØ i  ⟩
 (f Ģ‚ š‘©)(Ī» i →  ∣ h ∣ ((š‘Ø ⟦ t i ⟧) a))   ā‰”āŸØ ii ⟩
 (f Ģ‚ š‘©)(Ī» r → (š‘© ⟦ t r ⟧) (∣ h ∣ ∘ a))  āˆŽ
 where i  = ∄ h ∄ f Ī» r → (š‘Ø ⟦ t r ⟧) a
       ii = wd (f Ģ‚ š‘©)  ( Ī» i₁ → ∣ h ∣ ((š‘Ø ⟦ t i₁ ⟧) a) )
                       ( Ī» r → (š‘© ⟦ t r ⟧) (Ī» x → ∣ h ∣ (a x)) )
                       Ī» j → comm-hom-term wd š‘© h (t j) a
```


To conclude this module, we prove that every term is compatible with every
congruence relation. That is, if `t : Term X` and `Īø : Con š‘Ø`, then
`a Īø b → t(a) Īø t(b)`. (Recall, the compatibility relation `|:` was defined in
[Relations.Discrete][].)


```agda



module _ {α β : Level}{X : Type α} where

 open IsCongruence

 _∣:_ : {š‘Ø : Algebra α}(t : Term X)(Īø : Con{α}{β} š‘Ø) → (š‘Ø ⟦ t ⟧) |: ∣ Īø ∣
 ((ā„Š x) ∣: Īø) p = p x
 ((node f t) ∣: Īø) p = (is-compatible ∄ Īø ∄) f Ī» x → ((t x) ∣: Īø) p
```


**WARNING!** The compatibility relation for terms `∣:` is typed as \|:, whereas
the compatibility type for functions `|:` (defined in the
[Legacy.Base.Relations.Discrete][] module) is typed as `|:`.



#### <a id="substitution">Substitution</a>

A substitution from `Y` to `X` is simply a function from `Y` to `X`, and the
application of a substitution is represented as follows.


```agda


_[_] : {χ : Level}{X Y : Type χ} → Term Y → (Y → X) → Term X
(ā„Š y) [ σ ] = ā„Š (σ y)
(node f t)  [ σ ] = node f Ī» i → t i [ σ ]
```


Alternatively, we may want a substitution that replaces each variable symbol in
`Y`, not with an element of `X`, but with a term from `Term X`.


```agda


-- Substerm X Y, an inhabitant of which replaces each variable symbol in Y
-- with a term from Term X.
Substerm : (X Y : Type χ) → Type (ov χ)
Substerm X Y = (y : Y) → Term X

-- Application of a Substerm.
_[_]t : {X Y : Type χ } → Term Y → Substerm X Y → Term X
(ā„Š y) [ σ ]t = σ y
(node f t) [ σ ]t = node f (Ī» z → (t z) [ σ ]t )
```


Next we prove the important Substitution Theorem which asserts that an identity `p
ā‰ˆ q` holds in an algebra `š‘Ø` iff it holds in `š‘Ø` after applying any substitution.


```agda


subst-lemma :  swelldef š“„ α → {X Y : Type χ }(p : Term Y)(σ : Y → X)
               (š‘Ø : Algebra α)(Ī· : X → ∣ š‘Ø ∣)
 →             (š‘Ø ⟦ p [ σ ] ⟧) Ī· ≔ (š‘Ø ⟦ p ⟧) (Ī· ∘ σ)

subst-lemma _ (ā„Š x) σ š‘Ø Ī· = ≔.refl
subst-lemma wd (node f t) σ š‘Ø Ī· = wd (f Ģ‚ š‘Ø)  ( Ī» i → (š‘Ø ⟦ (t i) [ σ ] ⟧) Ī· )
                                             ( Ī» i → (š‘Ø ⟦ t i ⟧) (Ī· ∘ σ) )
                                             Ī» i → subst-lemma wd (t i) σ š‘Ø Ī·

subst-theorem :  swelldef š“„ α → {X Y : Type χ }
                 (p q : Term Y)(σ : Y → X)(š‘Ø : Algebra α)
 →               š‘Ø ⟦ p ⟧ ā‰ˆ š‘Ø ⟦ q ⟧ → š‘Ø ⟦ p [ σ ] ⟧ ā‰ˆ š‘Ø ⟦ q [ σ ] ⟧

subst-theorem wd p q σ š‘Ø Apq Ī· =
 (š‘Ø ⟦ p [ σ ] ⟧) Ī·  ā‰”āŸØ subst-lemma wd p σ š‘Ø Ī· ⟩
 (š‘Ø ⟦ p ⟧) (Ī· ∘ σ)  ā‰”āŸØ Apq (Ī· ∘ σ) ⟩
 (š‘Ø ⟦ q ⟧) (Ī· ∘ σ)  ā‰”āŸØ ≔.sym (subst-lemma wd q σ š‘Ø Ī·) ⟩
 (š‘Ø ⟦ q [ σ ] ⟧) Ī·  āˆŽ
```