forked from the1lab/1lab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Magma.lagda.md
162 lines (125 loc) · 4.47 KB
/
Magma.lagda.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<!--
```agda
open import 1Lab.Prelude
```
-->
```agda
module Algebra.Magma where
```
<!--
```agda
private variable
ℓ ℓ₁ : Level
A : Type ℓ
```
-->
# ∞-Magmas {defines="magma ∞-magma"}
In common mathematical parlance, a **magma** is a set equipped with a
binary operation. In HoTT, we free ourselves from considering sets as a
primitive, and generalise to ∞-groupoids: An **∞-magma** is a _type_
equipped with a binary operation.
```agda
is∞Magma : Type ℓ → Type ℓ
is∞Magma X = X → X → X
```
Since we can canonically identify the predicate `is∞Magma`{.Agda} with a
`Structure`{.Agda} built with the structure language, we automatically
get a notion of ∞-Magma homomorphism, and a proof that
`∞MagmaStr`{.Agda} is a `univalent structure`{.Agda ident=is-univalent}.
```agda
∞MagmaStr : Structure ℓ is∞Magma
∞MagmaStr = Term→structure (s∙ s→ (s∙ s→ s∙))
∞MagmaStr-univ : is-univalent (∞MagmaStr {ℓ = ℓ})
∞MagmaStr-univ = Term→structure-univalent (s∙ s→ (s∙ s→ s∙))
```
∞-magmas form a viable structure because magmas (and therefore their
higher version) do not axiomatize any _paths_ that would require
further coherence conditions. However, when considering structures with
equalities, like semigroups or loops, we must restrict ourselves to sets
to get a reasonable object, hence the field `has-is-set`{.Agda}.
To be able to properly generalize over these notions, we define magmas
as ∞-magmas whose carrier type is a set.
# Magmas
```agda
record is-magma {A : Type ℓ} (_⋆_ : A → A → A) : Type ℓ where
```
A **magma** is a `set`{.Agda ident=is-set} equipped with an arbitrary
binary operation `⋆`, on which no further laws are imposed.
```agda
field
has-is-set : is-set A
underlying-set : Set ℓ
underlying-set = el _ has-is-set
instance
magma-hlevel : ∀ {n} → H-Level A (2 + n)
magma-hlevel = basic-instance 2 has-is-set
open is-magma public
```
Note that we do not generally benefit from the [[set truncation]] of
arbitrary magmas - however, practically all structures built upon
`is-magma`{.Agda} do, since they contain paths which would require
complicated, if not outright undefinable, coherence conditions.
It also allows us to show that being a magma is a _property_:
```agda
is-magma-is-prop : {_⋆_ : A → A → A} → is-prop (is-magma _⋆_)
is-magma-is-prop x y i .has-is-set =
is-hlevel-is-prop 2 (x .has-is-set) (y .has-is-set) i
```
By turning the operation parameter into an additional piece of data, we
get the notion of a **magma structure** on a type, as well as the
notion of a magma in general by doing the same to the carrier type.
```agda
record Magma-on (A : Type ℓ) : Type ℓ where
field
_⋆_ : A → A → A
has-is-magma : is-magma _⋆_
open is-magma has-is-magma public
Magma : (ℓ : Level) → Type (lsuc ℓ)
Magma ℓ = Σ (Type ℓ) Magma-on
```
We then define what it means for an equivalence between the carrier
types of two given magmas to be an **equivalence of magmas**: it has to
preserve the magma operation.
```agda
record
Magma≃ (A B : Magma ℓ) (e : A .fst ≃ B .fst) : Type ℓ where
private
module A = Magma-on (A .snd)
module B = Magma-on (B .snd)
field
pres-⋆ : (x y : A .fst) → e .fst (x A.⋆ y) ≡ e .fst x B.⋆ e .fst y
open Magma≃
```
<!--
```agda
_ = Str-desc
```
-->
## The boolean implication magma
```agda
open import Data.Bool
```
To give a somewhat natural example for a magma that is neither
associative, commutative, nor has a two-sided identity element,
consider `boolean implication`{.Agda imp}. Since the booleans form a
set, this obviously defines a magma:
```agda
private
is-magma-imp : is-magma imp
is-magma-imp .has-is-set = Bool-is-set
```
We show it is not commutative or associative by giving counterexamples:
```agda
imp-not-commutative : ¬ ((x y : Bool) → imp x y ≡ imp y x)
imp-not-commutative commutative = true≠false (commutative false true)
imp-not-associative : ¬ ((x y z : Bool) → imp x (imp y z) ≡ imp (imp x y) z)
imp-not-associative associative = true≠false (associative false false false)
```
It also has no two-sided unit, as can be shown by case-splitting
on the candidates:
```agda
imp-not-unital
: (x : Bool) → ((y : Bool) → imp x y ≡ y) → ¬ ((y : Bool) → imp y x ≡ y)
imp-not-unital false left-unital right-unital = true≠false (right-unital false)
imp-not-unital true left-unital right-unital = true≠false (right-unital false)
```