I'd like to split up my definition of monoids into multiple parts:
- The signature of monoids
- The monoid laws, as a relation
- Witnesses of equality for elements that are in this relation
My current idea is to do it like the following:
data MonoidSig A : Type → Type₁ where
ε₀ : MonoidSig A A
_⋄₀_ : MonoidSig A (A → A → A)
RawMonoid : Type → Type₁
RawMonoid A = ∀ {B} → MonoidSig A B → B
module _ {A : Type} (rawMonoid : RawMonoid A) where
private
ε = rawMonoid ε₀
_⋄_ = rawMonoid _⋄₀_
data MonoidLaw : A → A → Type where
unit-l : ∀ x → MonoidLaw (ε ⋄ x) x
unit-r : ∀ x → MonoidLaw (x ⋄ ε) x
assoc : ∀ x y z → MonoidLaw ((x ⋄ y) ⋄ z) (x ⋄ (y ⋄ z))
Lawful : ∀ {A} (raw : RawMonoid A) → Set
Lawful raw = ∀ {x y} → MonoidLaw raw x y → x ≡ y
Monoid : (AIsSet : isSet A) → Type₁
Monoid {A = A} AIsSet = Σ[ raw ∈ RawMonoid A ] (Lawful raw)
Now, I'd like to make a datatype for free monoids as a quotient type of raw syntax quotiented by the monoid laws. But I haven't figured out how to get rid of the RawFreeMonoid definition below, and make it from MonoidSig somehow:
open import Cubical.HITs.SetQuotients
data RawFreeMonoid A : Type where
⟨_⟩ : A → RawFreeMonoid A
ε : RawFreeMonoid A
_⋄_ : RawFreeMonoid A → RawFreeMonoid A → RawFreeMonoid A
rawFreeMonoid : (A : Type) → RawMonoid (RawFreeMonoid A)
rawFreeMonoid A ε₀ = ε
rawFreeMonoid A _⋄₀_ = _⋄_
FreeMonoid : Type → Type
FreeMonoid A = RawFreeMonoid A / MonoidLaw (rawFreeMonoid A)
So that is my question: is there a way to define FreeMonoid in this way, without writing out by hand the RawFreeMonoid and rawFreeMonoid definitions?
Nice question! You can do it as follows (where I prefer to use an actual record type instead of an impredicative encoding):
For any given signature Σ,
Term Σwill then be the free Σ-structure. More precisely, for any sortsof Σ, the typeTerm Σ swill be the type of terms of sorts.The signature for monoids can be defined as follows:
Edit in response to the comment: You are right,
Term monoidSignatureis the free raw monoid, not the free monoid. I put up code for constructing the quotient here. I believe that in this code, the laws are specified in the way you want: