Skip to content

Commit 516c545

Browse files
Added some basic properties of bijections (#1528)
1 parent 231d210 commit 516c545

File tree

5 files changed

+180
-47
lines changed

5 files changed

+180
-47
lines changed

CHANGELOG.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ New modules
7373
Data.Rational.Unnormalised.Show
7474
```
7575

76+
* Properties of bijections:
77+
```
78+
Function.Properties.Bijection
79+
```
80+
7681
* Various system types and primitives:
7782
```
7883
System.Clock.Primitive
@@ -118,13 +123,23 @@ Other minor additions
118123
```
119124
and their corresponding algebraic substructures.
120125

121-
* In `Data.String.Properties`:
126+
* Added new proofs in `Data.String.Properties`:
122127
```
123128
≤-isDecTotalOrder-≈ : IsDecTotalOrder _≈_ _≤_
124129
≤-decTotalOrder-≈ : DecTotalOrder _ _ _
125130
```
126131

127-
* In `IO`:
132+
* Added new proofs in `Function.Construct.Symmetry`:
133+
```
134+
bijective : Bijective ≈₁ ≈₂ f → Symmetric ≈₂ → Transitive ≈₂ → Congruent ≈₁ ≈₂ f → Bijective ≈₂ ≈₁ f⁻¹
135+
isBijection : IsBijection ≈₁ ≈₂ f → Congruent ≈₂ ≈₁ f⁻¹ → IsBijection ≈₂ ≈₁ f⁻¹
136+
isBijection-≡ : IsBijection ≈₁ _≡_ f → IsBijection _≡_ ≈₁ f⁻¹
137+
bijection : Bijection R S → Congruent IB.Eq₂._≈_ IB.Eq₁._≈_ f⁻¹ → Bijection S R
138+
bijection-≡ : Bijection R (setoid B) → Bijection (setoid B) R
139+
sym-⤖ : A ⤖ B → B ⤖ A
140+
```
141+
142+
* Added new operations in `IO`:
128143
```
129144
Colist.forM : Colist A → (A → IO B) → IO (Colist B)
130145
Colist.forM′ : Colist A → (A → IO B) → IO ⊤
@@ -133,7 +148,7 @@ Other minor additions
133148
List.forM′ : List A → (A → IO B) → IO ⊤
134149
```
135150

136-
* In `IO.Base`:
151+
* Added new operations in `IO.Base`:
137152
```
138153
lift! : IO A → IO (Lift b A)
139154
_<$_ : B → IO A → IO B
@@ -148,8 +163,8 @@ Other minor additions
148163
untilJust : IO (Maybe A) → IO A
149164
```
150165

151-
* In `System.Exit`:
166+
* Added new operations in `System.Exit`:
152167
```
153168
isSuccess : ExitCode → Bool
154169
isFailure : ExitCode → Bool
155-
```
170+
```

src/Function/Construct/Symmetry.agda

Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88

99
module Function.Construct.Symmetry where
1010

11-
open import Data.Product using (_,_; swap)
11+
open import Data.Product using (_,_; swap; proj₁; proj₂)
1212
open import Function
1313
open import Level using (Level)
1414
open import Relation.Binary hiding (_⇔_)
15+
open import Relation.Binary.PropositionalEquality
1516

1617
private
1718
variable
@@ -23,6 +24,23 @@ private
2324
------------------------------------------------------------------------
2425
-- Properties
2526

27+
module _ {≈₁ : Rel A ℓ₁} {≈₂ : Rel B ℓ₂} {f : A B}
28+
((inj , surj) : Bijective ≈₁ ≈₂ f)
29+
where
30+
31+
private
32+
f⁻¹ = proj₁ ∘ surj
33+
f∘f⁻¹≡id = proj₂ ∘ surj
34+
35+
injective : Symmetric ≈₂ Transitive ≈₂ Congruent ≈₁ ≈₂ f Injective ≈₂ ≈₁ f⁻¹
36+
injective sym trans cong gx≈gy = trans (trans (sym (f∘f⁻¹≡id _)) (cong gx≈gy)) (f∘f⁻¹≡id _)
37+
38+
surjective : Surjective ≈₂ ≈₁ f⁻¹
39+
surjective x = f x , inj (proj₂ (surj (f x)))
40+
41+
bijective : Symmetric ≈₂ Transitive ≈₂ Congruent ≈₁ ≈₂ f Bijective ≈₂ ≈₁ f⁻¹
42+
bijective sym trans cong = injective sym trans cong , surjective
43+
2644
module _ (≈₁ : Rel A ℓ₁) (≈₂ : Rel B ℓ₂)
2745
(f : A B) {f⁻¹ : B A}
2846
where
@@ -39,85 +57,136 @@ module _ (≈₁ : Rel A ℓ₁) (≈₂ : Rel B ℓ₂)
3957
------------------------------------------------------------------------
4058
-- Structures
4159

60+
module _ {≈₁ : Rel A ℓ₁} {≈₂ : Rel B ℓ₂}
61+
{f : A B} (isBij : IsBijection ≈₁ ≈₂ f)
62+
where
63+
64+
private
65+
module IB = IsBijection isBij
66+
f⁻¹ = proj₁ ∘ IB.surjective
67+
68+
-- We can only flip a bijection if the witness produced by the
69+
-- surjection proof respects the equality on the codomain.
70+
isBijection : Congruent ≈₂ ≈₁ f⁻¹ IsBijection ≈₂ ≈₁ f⁻¹
71+
isBijection f⁻¹-cong = record
72+
{ isInjection = record
73+
{ isCongruent = record
74+
{ cong = f⁻¹-cong
75+
; isEquivalence₁ = IB.Eq₂.isEquivalence
76+
; isEquivalence₂ = IB.Eq₁.isEquivalence
77+
}
78+
; injective = injective IB.bijective IB.Eq₂.sym IB.Eq₂.trans IB.cong
79+
}
80+
; surjective = surjective {≈₂ = ≈₂} IB.bijective
81+
}
82+
83+
module _ {≈₁ : Rel A ℓ₁} {f : A B} (isBij : IsBijection ≈₁ _≡_ f) where
84+
85+
-- We can always flip a bijection if using the equality over the
86+
-- codomain is propositional equality.
87+
isBijection-≡ : IsBijection _≡_ ≈₁ _
88+
isBijection-≡ = isBijection isBij (IB.Eq₁.reflexive ∘ cong _)
89+
where module IB = IsBijection isBij
90+
4291
module _ {≈₁ : Rel A ℓ₁} {≈₂ : Rel B ℓ₂}
4392
{f : A B} {f⁻¹ : B A}
4493
where
4594

4695
isCongruent : IsCongruent ≈₁ ≈₂ f Congruent ≈₂ ≈₁ f⁻¹ IsCongruent ≈₂ ≈₁ f⁻¹
4796
isCongruent ic cg = record
48-
{ cong = cg
97+
{ cong = cg
4998
; isEquivalence₁ = IC.isEquivalence₂
5099
; isEquivalence₂ = IC.isEquivalence₁
51-
}
52-
where module IC = IsCongruent ic
100+
} where module IC = IsCongruent ic
53101

54102
isLeftInverse : IsRightInverse ≈₁ ≈₂ f f⁻¹ IsLeftInverse ≈₂ ≈₁ f⁻¹ f
55103
isLeftInverse inv = record
56104
{ isCongruent = isCongruent F.isCongruent F.cong₂
57-
; cong₂ = F.cong₁
58-
; inverseˡ = inverseˡ ≈₁ ≈₂ f {f⁻¹} F.inverseʳ
59-
}
60-
where module F = IsRightInverse inv
105+
; cong₂ = F.cong₁
106+
; inverseˡ = inverseˡ ≈₁ ≈₂ f {f⁻¹} F.inverseʳ
107+
} where module F = IsRightInverse inv
61108

62109
isRightInverse : IsLeftInverse ≈₁ ≈₂ f f⁻¹ IsRightInverse ≈₂ ≈₁ f⁻¹ f
63110
isRightInverse inv = record
64111
{ isCongruent = isCongruent F.isCongruent F.cong₂
65-
; cong₂ = F.cong₁
66-
; inverseʳ = inverseʳ ≈₁ ≈₂ f {f⁻¹} F.inverseˡ
67-
}
68-
where module F = IsLeftInverse inv
112+
; cong₂ = F.cong₁
113+
; inverseʳ = inverseʳ ≈₁ ≈₂ f {f⁻¹} F.inverseˡ
114+
} where module F = IsLeftInverse inv
69115

70116
isInverse : IsInverse ≈₁ ≈₂ f f⁻¹ IsInverse ≈₂ ≈₁ f⁻¹ f
71117
isInverse f-inv = record
72118
{ isLeftInverse = isLeftInverse F.isRightInverse
73-
; inverseʳ = inverseʳ ≈₁ ≈₂ f F.inverseˡ
74-
}
75-
where module F = IsInverse f-inv
119+
; inverseʳ = inverseʳ ≈₁ ≈₂ f F.inverseˡ
120+
} where module F = IsInverse f-inv
76121

77122
------------------------------------------------------------------------
78123
-- Setoid bundles
79124

125+
module _ {R : Setoid a ℓ₁} {S : Setoid b ℓ₂} (bij : Bijection R S) where
126+
127+
private
128+
module IB = Bijection bij
129+
f⁻¹ = proj₁ ∘ IB.surjective
130+
131+
-- We can only flip a bijection if the witness produced by the
132+
-- surjection proof respects the equality on the codomain.
133+
bijection : Congruent IB.Eq₂._≈_ IB.Eq₁._≈_ f⁻¹ Bijection S R
134+
bijection cong = record
135+
{ f = f⁻¹
136+
; cong = cong
137+
; bijective = bijective IB.bijective IB.Eq₂.sym IB.Eq₂.trans IB.cong
138+
}
139+
140+
-- We can always flip a bijection if using the equality over the
141+
-- codomain is propositional equality.
142+
bijection-≡ : {R : Setoid a ℓ₁} {B : Set b}
143+
Bijection R (setoid B) Bijection (setoid B) R
144+
bijection-≡ bij = bijection bij (B.Eq₁.reflexive ∘ cong _)
145+
where module B = Bijection bij
146+
80147
module _ {R : Setoid a ℓ₁} {S : Setoid b ℓ₂} where
81148

82149
equivalence : Equivalence R S Equivalence S R
83150
equivalence equiv = record
84-
{ f = E.g
85-
; g = E.f
151+
{ f = E.g
152+
; g = E.f
86153
; cong₁ = E.cong₂
87154
; cong₂ = E.cong₁
88-
}
89-
where module E = Equivalence equiv
155+
} where module E = Equivalence equiv
90156

91157
rightInverse : LeftInverse R S RightInverse S R
92158
rightInverse left = record
93-
{ f = L.g
94-
; g = L.f
95-
; cong₁ = L.cong₂
96-
; cong₂ = L.cong₁
159+
{ f = L.g
160+
; g = L.f
161+
; cong₁ = L.cong₂
162+
; cong₂ = L.cong₁
97163
; inverseʳ = L.inverseˡ
98164
} where module L = LeftInverse left
99165

100166
leftInverse : RightInverse R S LeftInverse S R
101167
leftInverse right = record
102-
{ f = R.g
103-
; g = R.f
168+
{ f = R.g
169+
; g = R.f
104170
; cong₁ = R.cong₂
105171
; cong₂ = R.cong₁
106172
; inverseˡ = R.inverseʳ
107173
} where module R = RightInverse right
108174

109175
inverse : Inverse R S Inverse S R
110176
inverse inv = record
111-
{ f = I.f⁻¹
112-
; f⁻¹ = I.f
113-
; cong₁ = I.cong₂
114-
; cong₂ = I.cong₁
177+
{ f = I.f⁻¹
178+
; f⁻¹ = I.f
179+
; cong₁ = I.cong₂
180+
; cong₂ = I.cong₁
115181
; inverse = swap I.inverse
116182
} where module I = Inverse inv
117183

118184
------------------------------------------------------------------------
119185
-- Propositional bundles
120186

187+
sym-⤖ : A ⤖ B B ⤖ A
188+
sym-⤖ b = bijection b (cong _)
189+
121190
sym-⇔ : A ⇔ B B ⇔ A
122191
sym-⇔ = equivalence
123192

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Some basic properties of bijections. This file is designed to be
5+
-- imported qualified.
6+
------------------------------------------------------------------------
7+
8+
{-# OPTIONS --without-K --safe #-}
9+
10+
module Function.Properties.Bijection where
11+
12+
open import Function.Bundles using (Bijection; _⤖_)
13+
open import Level using (Level)
14+
open import Relation.Binary
15+
import Relation.Binary.PropositionalEquality as P
16+
17+
import Function.Construct.Identity as Identity
18+
import Function.Construct.Symmetry as Symmetry
19+
import Function.Construct.Composition as Composition
20+
21+
private
22+
variable
23+
a b c ℓ ℓ₁ ℓ₂ ℓ₃ : Level
24+
A B : Set a
25+
T S : Setoid a ℓ
26+
27+
------------------------------------------------------------------------
28+
-- Setoid properties
29+
30+
refl : Reflexive (Bijection {a} {ℓ})
31+
refl = Identity.bijection _
32+
33+
-- Can't prove full symmetry as we have no proof that the witness
34+
-- produced by the surjection proof preserves equality
35+
sym-≡ : Bijection S (P.setoid B) Bijection (P.setoid B) S
36+
sym-≡ = Symmetry.bijection-≡
37+
38+
trans : Trans (Bijection {a} {ℓ₁} {b} {ℓ₂}) (Bijection {b} {ℓ₂} {c} {ℓ₃}) Bijection
39+
trans = Composition.bijection
40+
41+
------------------------------------------------------------------------
42+
-- Propositional properties
43+
44+
⤖-isEquivalence : IsEquivalence {ℓ = ℓ} _⤖_
45+
⤖-isEquivalence = record
46+
{ refl = refl
47+
; sym = sym-≡
48+
; trans = trans
49+
}

src/Function/Properties/Equivalence.agda

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
------------------------------------------------------------------------
22
-- The Agda standard library
33
--
4-
-- An Equivalence (on functions) is an Equivalence relation
5-
-- This file is meant to be imported qualified.
4+
-- Some basic properties of equivalences. This file is designed to be
5+
-- imported qualified.
66
------------------------------------------------------------------------
77

88
{-# OPTIONS --without-K --safe #-}
@@ -20,12 +20,12 @@ import Function.Construct.Composition as Composition
2020

2121
private
2222
variable
23-
a b ℓ₁ ℓ₂ : Level
23+
a : Level
2424

2525
------------------------------------------------------------------------
2626
-- Setoid bundles
2727

28-
isEquivalence : IsEquivalence (Equivalence {a} {b})
28+
isEquivalence : IsEquivalence (Equivalence {a} {})
2929
isEquivalence = record
3030
{ refl = λ {x} Identity.equivalence x
3131
; sym = Symmetry.equivalence
@@ -35,7 +35,7 @@ isEquivalence = record
3535
------------------------------------------------------------------------
3636
-- Propositional bundles
3737

38-
⇔-isEquivalence : IsEquivalence {ℓ =} _⇔_
38+
⇔-isEquivalence : IsEquivalence {ℓ = ℓ} _⇔_
3939
⇔-isEquivalence = record
4040
{ refl = λ {x} Identity.equivalence (setoid x)
4141
; sym = Symmetry.equivalence

src/Function/Properties/Inverse.agda

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,33 @@ module Function.Properties.Inverse where
1212
open import Function.Bundles using (Inverse; _↔_)
1313
open import Level using (Level)
1414
open import Relation.Binary using (Setoid; IsEquivalence)
15-
open import Relation.Binary.PropositionalEquality using (setoid)
15+
import Relation.Binary.PropositionalEquality as P
1616

1717
import Function.Construct.Identity as Identity
1818
import Function.Construct.Symmetry as Symmetry
1919
import Function.Construct.Composition as Composition
2020

2121
private
2222
variable
23-
a b ℓ₁ ℓ₂ : Level
23+
a : Level
2424

2525
------------------------------------------------------------------------
2626
-- Setoid bundles
2727

28-
isEquivalence : IsEquivalence (Inverse {a} {b})
28+
isEquivalence : IsEquivalence (Inverse {a} {})
2929
isEquivalence = record
30-
{ refl = λ {x} Identity.inverse x
31-
; sym = Symmetry.inverse
30+
{ refl = λ {x} Identity.inverse x
31+
; sym = Symmetry.inverse
3232
; trans = Composition.inverse
3333
}
3434

3535
------------------------------------------------------------------------
3636
-- Propositional bundles
3737

3838
-- need to η-expand for everything to line up properly
39-
↔-isEquivalence : IsEquivalence {ℓ =} _↔_
39+
↔-isEquivalence : IsEquivalence {ℓ = ℓ} _↔_
4040
↔-isEquivalence = record
41-
{ refl = λ {x} Identity.inverse (setoid x)
42-
; sym = Symmetry.inverse
41+
{ refl = λ {x} Identity.inverse (P.setoid x)
42+
; sym = Symmetry.inverse
4343
; trans = Composition.inverse
4444
}

0 commit comments

Comments
 (0)