---
layout: default
title : "Legacy.Base.Algebras.Products module (Agda Universal Algebra Library)"
date : "2021-01-12"
author: "agda-algebras development team"
---

### <a id="products-of-algebras-and-product-algebras">Products of Algebras and Product Algebras</a>

This is the [Legacy.Base.Algebras.Products][] module of the [Agda Universal Algebra Library][].


```agda


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

open import Overture using ( ๐“ž ; ๐“ฅ ; Signature )

module Legacy.Base.Algebras.Products {๐‘† : 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 Level           using ( Level ; _โŠ”_ ; suc )
open import Relation.Unary  using ( Pred ; _โІ_ ; _โˆˆ_ )

-- Imports from agda-algebras ---------------------------------------------------
open import Overture                     using (_โปยน; ๐‘–๐‘‘; โˆฃ_โˆฃ; โˆฅ_โˆฅ)
open import Legacy.Base.Algebras.Basic {๐‘† = ๐‘†}  using ( Algebra ; _ฬ‚_ ; algebra )

private variable ฮฑ ฮฒ ฯ ๐“˜ : Level
```


From now on, the modules of the
[agda-algebras](https://github.com/ualib/agda-algebras) library will assume a
fixed signature `๐‘† : Signature ๐“ž ๐“ฅ`.

Recall the informal definition of a *product* of `๐‘†`-algebras. Given a type `I :
Type ๐“˜` and a family `๐’œ : I โ†’ Algebra ฮฑ`, the *product* `โจ… ๐’œ` is the algebra
whose domain is the Cartesian product `ฮ  ๐‘– ๊ž‰ I , โˆฃ ๐’œ ๐‘– โˆฃ` of the domains of the
algebras in `๐’œ`, and whose operations are defined as follows: if `๐‘“` is a `J`-ary
operation symbol and if `๐‘Ž : ฮ  ๐‘– ๊ž‰ I , J โ†’ ๐’œ ๐‘–` is an `I`-tuple of `J`-tuples such
that `๐‘Ž ๐‘–` is a `J`-tuple of elements of `๐’œ ๐‘–` (for each `๐‘–`), then `(๐‘“ ฬ‚ โจ… ๐’œ) ๐‘Ž :=
(i : I) โ†’ (๐‘“ ฬ‚ ๐’œ i)(๐‘Ž i)`.

In the [agda-algebras](https://github.com/ualib/agda-algebras) library a *product
of* `๐‘†`-*algebras* is represented by the following type.


```agda


โจ… : {I : Type ๐“˜ }(๐’œ : I โ†’ Algebra ฮฑ ) โ†’ Algebra (๐“˜ โŠ” ฮฑ)

โจ… {I = I} ๐’œ =  ( โˆ€ (i : I) โ†’ โˆฃ ๐’œ i โˆฃ ) ,        -- domain of the product algebra
                ฮป ๐‘“ ๐‘Ž i โ†’ (๐‘“ ฬ‚ ๐’œ i) ฮป x โ†’ ๐‘Ž x i  -- basic operations of the product algebra
```


The type just defined is the one that will be used throughout the
[agda-algebras](https://github.com/ualib/agda-algebras) library whenever the
product of an indexed collection of algebras (of type `Algebra`) is required.
However, for the sake of completeness, here is how one could define a type
representing the product of algebras inhabiting the record type `algebra`. 


```agda


open algebra

โจ…' : {I : Type ๐“˜ }(๐’œ : I โ†’ algebra ฮฑ) โ†’ algebra (๐“˜ โŠ” ฮฑ)
โจ…' {I} ๐’œ = record  { carrier = โˆ€ i โ†’ carrier (๐’œ i)                         -- domain
                    ; opsymbol = ฮป ๐‘“ ๐‘Ž i โ†’ (opsymbol (๐’œ i)) ๐‘“ ฮป x โ†’ ๐‘Ž x i }  -- basic operations
```


**Notation**. Given a signature `๐‘† : Signature ๐“ž ๐“ฅ`, the type `Algebra ฮฑ` has
type `Type(๐“ž โŠ” ๐“ฅ โŠ” lsuc ฮฑ)`.  Such types occur so often in the
[agda-algebras](https://github.com/ualib/agda-algebras) library that we define
the following shorthand for their universes.


```agda


ov : Level โ†’ Level
ov ฮฑ = ๐“ž โŠ” ๐“ฅ โŠ” suc ฮฑ
```



### <a id="products-of-classes-of-algebras">Products of classes of algebras</a>

An arbitrary class `๐’ฆ` of algebras is represented as a predicate over the type
`Algebra ฮฑ`, for some universe level `ฮฑ` and signature `๐‘†`. That is, `๐’ฆ : Pred
(Algebra ฮฑ) ฮฒ`, for some type `ฮฒ`. Later we will formally state and prove that
the product of all subalgebras of algebras in `๐’ฆ` belongs to the class `SP(๐’ฆ)` of
subalgebras of products of algebras in `๐’ฆ`. That is, `โจ… S(๐’ฆ) โˆˆ SP(๐’ฆ )`. This turns
out to be a nontrivial exercise.

To begin, we need to define types that represent products over arbitrary
(nonindexed) families such as `๐’ฆ` or `S(๐’ฆ)`. Observe that `ฮ  ๐’ฆ` is certainly not
what we want.  For recall that `Pred (Algebra ฮฑ) ฮฒ` is just an alias for the
function type `Algebra ฮฑ โ†’ Type ฮฒ`, and the semantics of the latter takes `๐’ฆ ๐‘จ`
(and `๐‘จ โˆˆ ๐’ฆ`) to mean that `๐‘จ` belongs to the class `๐’ฆ`. Thus, by definition,

    ฮ  ๐’ฆ   :=   ฮ  ๐‘จ ๊ž‰ (Algebra ฮฑ) , ๐’ฆ ๐‘จ   :=   โˆ€ (๐‘จ : Algebra ฮฑ) โ†’ ๐‘จ โˆˆ ๐’ฆ,

which asserts that every inhabitant of the type `Algebra ฮฑ` belongs to `๐’ฆ`.
Evidently this is not the product algebra that we seek.

What we need is a type that serves to index the class `๐’ฆ`, and a function `๐”„` that
maps an index to the inhabitant of `๐’ฆ` at that index. But `๐’ฆ` is a predicate (of
type `(Algebra ฮฑ) โ†’ Type ฮฒ`) and the type `Algebra ฮฑ` seems rather nebulous in
that there is no natural indexing class with which to "enumerate" all inhabitants
of `Algebra ฮฑ` belonging to `๐’ฆ`.

The solution is to essentially take `๐’ฆ` itself to be the indexing type, at least
heuristically that is how one can view the type `โ„‘` that we now define.


```agda


module _ {๐’ฆ : Pred (Algebra ฮฑ)(ov ฮฑ)} where
 โ„‘ : Type (ov ฮฑ)
 โ„‘ = ฮฃ[ ๐‘จ โˆˆ Algebra ฮฑ ] ๐‘จ โˆˆ ๐’ฆ
```


Taking the product over the index type `โ„‘` requires a function that maps an index
`i : โ„‘` to the corresponding algebra.  Each `i : โ„‘` is a pair, `(๐‘จ , p)`, where
`๐‘จ` is an algebra and `p` is a proof that `๐‘จ` belongs to `๐’ฆ`, so the function
mapping an index to the corresponding algebra is simply the first projection.


```agda


 ๐”„ : โ„‘ โ†’ Algebra ฮฑ
 ๐”„ i = โˆฃ i โˆฃ
```


Finally, we define `class-product` which represents the product of all members of
๐’ฆ.


```agda


 class-product : Algebra (ov ฮฑ)
 class-product = โจ… ๐”„
```


If `p : ๐‘จ โˆˆ ๐’ฆ`, we view the pair `(๐‘จ , p) โˆˆ โ„‘` as an *index* over the class, so we
can think of `๐”„ (๐‘จ , p)` (which is simply `๐‘จ`) as the projection of the product `โจ…
๐”„` onto the `(๐‘จ , p)`-th component.