Skip to content

Commit 2d38f31

Browse files
Change argument order for binary reasoning combinators (#1045)
1 parent 423a351 commit 2d38f31

File tree

24 files changed

+416
-169
lines changed

24 files changed

+416
-169
lines changed

CHANGELOG.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,67 @@ Bug-fixes
2121
Non-backwards compatible changes
2222
--------------------------------
2323

24+
#### Changes to how equational reasoning is implemented
25+
26+
* NOTE: __Uses__ of equational reasoning remains unchanged. These changes should only
27+
affect users who are renaming/hiding the library's equational reasoning combinators.
28+
29+
* Previously all equational reasoning combinators (e.g. `_≈⟨_⟩_`, `_≡⟨_⟩_`, `_≤⟨_⟩_`)
30+
have been defined in the following style:
31+
```agda
32+
infixr 2 _≡⟨_⟩_
33+
34+
_≡⟨_⟩_ : ∀ x {y z : A} → x ≡ y → y ≡ z → x ≡ z
35+
_ ≡⟨ x≡y ⟩ y≡z = trans x≡y y≡z
36+
```
37+
The type checker therefore infers the RHS of the equational step from the LHS + the
38+
type of the proof. For example for `x ≈⟨ x≈y ⟩ y ∎` it is inferred that `y ∎`
39+
must have type `y IsRelatedTo y` from `x : A` and `x≈y : x ≈ y`.
40+
41+
* There are two problems with this. Firstly, it means that the reasoning combinators are
42+
not compatible with macros (i.e. tactics) that attempt to automatically generate proofs
43+
for `x≈y`. This is because the reflection machinary does not have access to the type of RHS
44+
as it cannot be inferred. In practice this meant that the new reflective solvers
45+
`Tactic.RingSolver` and `Tactic.MonoidSolver` could not be used inside the equational
46+
reasoning. Secondly the inference procedure itself is slower as described in this
47+
[exchange](https://lists.chalmers.se/pipermail/agda/2016/009090.html)
48+
on the Agda mailing list.
49+
50+
* Therefore, as suggested on the mailing list, the order of arguments to the combinators
51+
have been reversed so that instead the type of the proof is inferred from the LHS + RHS.
52+
```agda
53+
infixr -2 step-≡
54+
55+
step-≡ : ∀ x {y z : A} → y ≡ z → x ≡ y → x ≡ z
56+
step-≡ y≡z x≡y = trans x≡y y≡z
57+
58+
syntax step-≡ x y≡z x≡y = x ≡⟨ x≡y ⟩ y≡z
59+
```
60+
where the `syntax` declaration is then used to recover the original order of the arguments.
61+
This change enables the use of macros and anecdotally speeds up type checking by a
62+
factor of 5.
63+
64+
* No changes are needed when defining new combinators, as the old and new styles are
65+
compatible. Having said that you may want to switch to the new style for the benefits
66+
described above.
67+
68+
* One drawback is that hiding and renaming the combinators no longer works as before,
69+
as `_≡⟨_⟩_` etc. are now syntax instead of names. For example instead of:
70+
```agda
71+
open SetoidReasoning hiding (_≈⟨_⟩_) renaming (_≡⟨_⟩_ to _↭⟨_⟩_)
72+
```
73+
one must now write :
74+
```agda
75+
open SetoidReasoning hiding (step-≈; step-≡)
76+
77+
infixr 2 step-↭
78+
step-↭ = step-≡
79+
syntax step-↭ x y≡z x≡y = x ≡⟨ x≡y ⟩ y≡z
80+
```
81+
This is more verbose than before, but we hope that the advantages outlined above
82+
outweigh this minor inconvenience. (As an aside, it is hoped that at some point Agda might
83+
provide the ability to rename syntax that automatically generates the above boilerplate).
84+
2485
#### Tweak to definition of `Permutation.refl`
2586

2687
* The definition of `refl` in `Data.List.Relation.Binary.Permutation.Homogeneous/Setoid`

README/Data/Nat.agda

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ ex₃ m n = *-comm m n
3939
-- provides some combinators for equational reasoning.
4040

4141
open Relation.Binary.PropositionalEquality using (cong; module ≡-Reasoning)
42-
open ≡-Reasoning using (begin_; _≡⟨_⟩_; _∎)
4342

4443
ex₄ : m n m * (n + 0) ≡ n * m
4544
ex₄ m n = begin
4645
m * (n + 0) ≡⟨ cong (_*_ m) (+-identityʳ n) ⟩
4746
m * n ≡⟨ *-comm m n ⟩
4847
n * m ∎
48+
where open ≡-Reasoning
4949

5050
-- The module SemiringSolver in Data.Nat.Solver contains a solver
5151
-- for natural number equalities involving variables, constants, _+_

src/Codata/Musical/Colist.agda

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -457,10 +457,15 @@ Any-∈ {P = P} = record
457457
antisym [] [] = []
458458
antisym (x ∷ p₁) p₂ = x ∷ ♯ antisym (♭ p₁) (tail p₂)
459459

460-
module ⊑-Reasoning where
461-
private
462-
open module R {a} {A : Set a} = POR (⊑-Poset A)
463-
public renaming (_≤⟨_⟩_ to _⊑⟨_⟩_)
460+
module ⊑-Reasoning {a} {A : Set a} where
461+
private module Base = POR (⊑-Poset A)
462+
463+
open Base public
464+
hiding (step-<; begin-strict_; step-≤)
465+
466+
infixr 2 step-⊑
467+
step-⊑ = Base.step-≤
468+
syntax step-⊑ x ys⊑zs xs⊑ys = x ⊑⟨ xs⊑ys ⟩ ys⊑zs
464469

465470
-- The subset relation forms a preorder.
466471

@@ -469,16 +474,22 @@ module ⊑-Reasoning where
469474
(λ xs≈ys ⊑⇒⊆ (⊑P.reflexive xs≈ys))
470475
where module ⊑P = Poset (⊑-Poset A)
471476

472-
module ⊆-Reasoning where
473-
private
474-
open module R {a} {A : Set a} = PreR (⊆-Preorder A)
475-
public renaming (_∼⟨_⟩_ to _⊆⟨_⟩_)
477+
module ⊆-Reasoning {a} {A : Set a} where
478+
private module Base = PreR (⊆-Preorder A)
479+
480+
open Base public
481+
hiding (step-∼)
482+
483+
infixr 2 step-⊆
484+
infix 1 step-∈
485+
486+
step-⊆ = Base.step-∼
476487

477-
infix 1 _∈⟨_⟩_
488+
step-∈ : (x : A) {xs ys} xs IsRelatedTo ys x ∈ xs x ∈ ys
489+
step-∈ x xs⊆ys x∈xs = (begin xs⊆ys) x∈xs
478490

479-
_∈⟨_⟩_ : {a} {A : Set a} (x : A) {xs ys}
480-
x ∈ xs xs IsRelatedTo ys x ∈ ys
481-
x ∈⟨ x∈xs ⟩ xs⊆ys = (begin xs⊆ys) x∈xs
491+
syntax step-⊆ xs ys⊆zs xs⊆ys = xs ⊆⟨ xs⊆ys ⟩ ys⊆zs
492+
syntax step-∈ x xs⊆ys x∈xs = x ∈⟨ x∈xs ⟩ xs⊆ys
482493

483494
-- take returns a prefix.
484495

src/Data/Integer/Divisibility.agda

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
--
44
-- Unsigned divisibility
55
------------------------------------------------------------------------
6+
67
-- For signed divisibility see `Data.Integer.Divisibility.Signed`
78

89
{-# OPTIONS --without-K --safe #-}

src/Data/Integer/Divisibility/Signed.agda

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,19 @@ open _∣_ using (quotient) public
110110
∣-preorder : Preorder _ _ _
111111
∣-preorder = record { isPreorder = ∣-isPreorder }
112112

113-
module ∣-Reasoning = PreorderReasoning ∣-preorder
114-
hiding (_≈⟨_⟩_)
115-
renaming (_∼⟨_⟩_ to _∣⟨_⟩_)
113+
------------------------------------------------------------------------
114+
-- Divisibility reasoning
115+
116+
module ∣-Reasoning where
117+
private
118+
module Base = PreorderReasoning ∣-preorder
119+
120+
open Base public
121+
hiding (step-∼; step-≈; step-≈˘)
122+
123+
infixr 2 step-∣
124+
step-∣ = Base.step-∼
125+
syntax step-∣ x y∣z x∣y = x ∣⟨ x∣y ⟩ y∣z
116126

117127
------------------------------------------------------------------------
118128
-- Other properties of _∣_

src/Data/Integer/Properties.agda

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ module ≤-Reasoning where
306306
<-≤-trans
307307
≤-<-trans
308308
public
309-
hiding (_≈⟨_⟩_; _≈˘⟨_⟩_)
309+
hiding (step-≈; step-≈˘)
310310

311311
------------------------------------------------------------------------
312312
-- Properties of -_

src/Data/List/Relation/Binary/BagAndSetEquality.agda

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,24 @@ module ⊆-Reasoning where
8787
module PreOrder {a} {A : Set a} = PreorderReasoning (⊆-preorder A)
8888

8989
open PreOrder
90-
hiding (_≈⟨_⟩_; _≈˘⟨_⟩_)
91-
renaming (_∼⟨_⟩_ to _⊆⟨_⟩_)
90+
hiding (step-≈; step-≈˘; step-∼)
9291

93-
infixr 2 _∼⟨_⟩_
94-
infix 1 _∈⟨_⟩_
92+
infixr 2 step-∼ step-⊆
93+
infix 1 step-∈
9594

96-
_∈⟨_⟩_ : {a} {A : Set a} x {xs ys : List A}
97-
x ∈ xs xs IsRelatedTo ys x ∈ ys
98-
x ∈⟨ x∈xs ⟩ xs⊆ys = (begin xs⊆ys) x∈xs
95+
step-⊆ = PreOrder.step-∼
9996

100-
_∼⟨_⟩_ : {k a} {A : Set a} xs {ys zs : List A}
101-
xs ∼[ ⌊ k ⌋→ ] ys ys IsRelatedTo zs xs IsRelatedTo zs
102-
xs ∼⟨ xs≈ys ⟩ ys≈zs = xs ⊆⟨ ⇒→ xs≈ys ⟩ ys≈zs
97+
step-∈ : {a} {A : Set a} x {xs ys : List A}
98+
xs IsRelatedTo ys x ∈ xs x ∈ ys
99+
step-∈ x xs⊆ys x∈xs = (begin xs⊆ys) x∈xs
100+
101+
step-∼ : {k a} {A : Set a} xs {ys zs : List A}
102+
ys IsRelatedTo zs xs ∼[ ⌊ k ⌋→ ] ys xs IsRelatedTo zs
103+
step-∼ xs ys⊆zs xs≈ys = step-⊆ xs ys⊆zs (⇒→ xs≈ys)
104+
105+
syntax step-∈ x xs⊆ys x∈xs = x ∈⟨ x∈xs ⟩ xs⊆ys
106+
syntax step-∼ xs ys⊆zs xs≈ys = xs ∼⟨ xs≈ys ⟩ ys⊆zs
107+
syntax step-⊆ xs ys⊆zs xs⊆ys = xs ⊆⟨ xs⊆ys ⟩ ys⊆zs
103108

104109
------------------------------------------------------------------------
105110
-- Congruence lemmas

src/Data/List/Relation/Binary/Permutation/Propositional.agda

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,28 @@ data _↭_ : Rel (List A) a where
6767

6868
module PermutationReasoning where
6969

70-
open EqReasoning ↭-setoid
71-
using (_IsRelatedTo_; relTo)
70+
private
71+
module Base = EqReasoning ↭-setoid
7272

7373
open EqReasoning ↭-setoid public
74-
using (begin_ ; _∎ ; _≡⟨⟩_; _≡⟨_⟩_)
75-
renaming (_≈⟨_⟩_ to _↭⟨_⟩_; _≈˘⟨_⟩_ to _↭˘⟨_⟩_)
74+
hiding (step-≈; step-≈˘)
7675

77-
infixr 2 _∷_<⟨_⟩_ _∷_∷_<<⟨_⟩_
76+
infixr 2 step-↭ step-↭˘ step-swap step-prep
77+
78+
step-↭ = Base.step-≈
79+
step-↭˘ = Base.step-≈˘
7880

7981
-- Skip reasoning on the first element
80-
_∷_<⟨_⟩_ : x xs {ys zs : List A} xs ↭ ys
81-
(x ∷ ys) IsRelatedTo zs (x ∷ xs) IsRelatedTo zs
82-
x ∷ xs <⟨ xs↭ys ⟩ rel = relTo (trans (prep x xs↭ys) (begin rel))
82+
step-prep : x xs {ys zs : List A} (x ∷ ys) IsRelatedTo zs
83+
xs ↭ ys (x ∷ xs) IsRelatedTo zs
84+
step-prep x xs rel xs↭ys = relTo (trans (prep x xs↭ys) (begin rel))
8385

8486
-- Skip reasoning about the first two elements
85-
_∷_∷_<<⟨_⟩_ : x y xs {ys zs : List A} xs ↭ ys
86-
(y ∷ x ∷ ys) IsRelatedTo zs (x ∷ y ∷ xs) IsRelatedTo zs
87-
x ∷ y ∷ xs <<⟨ xs↭ys ⟩ rel = relTo (trans (swap x y xs↭ys) (begin rel))
87+
step-swap : x y xs {ys zs : List A} (y ∷ x ∷ ys) IsRelatedTo zs
88+
xs ↭ ys (x ∷ y ∷ xs) IsRelatedTo zs
89+
step-swap x y xs rel xs↭ys = relTo (trans (swap x y xs↭ys) (begin rel))
90+
91+
syntax step-↭ x y↭z x↭y = x ↭⟨ x↭y ⟩ y↭z
92+
syntax step-↭˘ x y↭z y↭x = x ↭˘⟨ y↭x ⟩ y↭z
93+
syntax step-prep x xs y↭z x↭y = x ∷ xs <⟨ x↭y ⟩ y↭z
94+
syntax step-swap x y xs y↭z x↭y = x ∷ y ∷ xs <<⟨ x↭y ⟩ y↭z

src/Data/List/Relation/Binary/Permutation/Setoid.agda

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,27 +72,38 @@ _↭_ = Homogeneous.Permutation _≈_
7272

7373
module PermutationReasoning where
7474

75-
open SetoidReasoning ↭-setoid
76-
using (_IsRelatedTo_; relTo)
75+
private
76+
module Base = SetoidReasoning ↭-setoid
7777

7878
open SetoidReasoning ↭-setoid public
79-
using (begin_ ; _∎ ; _≡⟨⟩_; _≡⟨_⟩_)
80-
renaming (_≈⟨_⟩_ to _↭⟨_⟩_; _≈˘⟨_⟩_ to _↭˘⟨_⟩_)
79+
hiding (step-≈; step-≈˘)
8180

82-
infixr 2 _∷_<⟨_⟩_ _∷_∷_<<⟨_⟩_ _≋⟨_⟩_ _≋˘⟨_⟩_
81+
infixr 2 step-↭ step-↭˘ step-≋ step-≋˘ step-swap step-prep
8382

84-
-- Skip reasoning on the first element
85-
_∷_<⟨_⟩_ : x xs {ys zs : List A} xs ↭ ys
86-
(x ∷ ys) IsRelatedTo zs (x ∷ xs) IsRelatedTo zs
87-
x ∷ xs <⟨ xs↭ys ⟩ rel = relTo (trans (↭-prep _ xs↭ys) (begin rel))
83+
step-↭ = Base.step-≈
84+
step-↭˘ = Base.step-≈˘
8885

89-
-- Skip reasoning about the first two elements
90-
_∷_∷_<<⟨_⟩_ : x y xs {ys zs : List A} xs ↭ ys
91-
(y ∷ x ∷ ys) IsRelatedTo zs (x ∷ y ∷ xs) IsRelatedTo zs
92-
x ∷ y ∷ xs <<⟨ xs↭ys ⟩ rel = relTo (trans (↭-swap _ _ xs↭ys) (begin rel))
86+
-- Step with pointwise list equality
87+
step-≋ : x {y z} y IsRelatedTo z x ≋ y x IsRelatedTo z
88+
step-≋ x (relTo y↔z) x≋y = relTo (trans (refl x≋y) y↔z)
9389

94-
_≋⟨_⟩_ : x {y z} x ≋ y y IsRelatedTo z x IsRelatedTo z
95-
x ≋⟨ x≈y ⟩ (relTo y↔z) = relTo (trans (refl x≈y) y↔z)
90+
-- Step with flipped pointwise list equality
91+
step-≋˘ : x {y z} y IsRelatedTo z y ≋ x x IsRelatedTo z
92+
step-≋˘ x y↭z y≋x = x ≋⟨ ≋-sym y≋x ⟩ y↭z
9693

97-
_≋˘⟨_⟩_ : x {y z} y ≋ x y IsRelatedTo z x IsRelatedTo z
98-
x ≋˘⟨ y≈x ⟩ y∼z = x ≋⟨ ≋-sym y≈x ⟩ y∼z
94+
-- Skip reasoning on the first element
95+
step-prep : x xs {ys zs : List A} (x ∷ ys) IsRelatedTo zs
96+
xs ↭ ys (x ∷ xs) IsRelatedTo zs
97+
step-prep x xs rel xs↭ys = relTo (trans (prep Eq.refl xs↭ys) (begin rel))
98+
99+
-- Skip reasoning about the first two elements
100+
step-swap : x y xs {ys zs : List A} (y ∷ x ∷ ys) IsRelatedTo zs
101+
xs ↭ ys (x ∷ y ∷ xs) IsRelatedTo zs
102+
step-swap x y xs rel xs↭ys = relTo (trans (swap Eq.refl Eq.refl xs↭ys) (begin rel))
103+
104+
syntax step-↭ x y↭z x↭y = x ↭⟨ x↭y ⟩ y↭z
105+
syntax step-↭˘ x y↭z y↭x = x ↭˘⟨ y↭x ⟩ y↭z
106+
syntax step-≋ x y↭z x≋y = x ≋⟨ x≋y ⟩ y↭z
107+
syntax step-≋˘ x y↭z y≋x = x ≋˘⟨ y≋x ⟩ y↭z
108+
syntax step-prep x xs y↭z x↭y = x ∷ xs <⟨ x↭y ⟩ y↭z
109+
syntax step-swap x y xs y↭z x↭y = x ∷ y ∷ xs <<⟨ x↭y ⟩ y↭z

src/Data/List/Relation/Binary/Subset/Propositional/Properties.agda

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ module _ {a} (A : Set a) where
7070

7171
module ⊆-Reasoning {a} (A : Set a) where
7272
open Setoidₚ.⊆-Reasoning (setoid A) public
73-
hiding (_≋⟨_⟩_; _≋˘⟨_⟩_; _≋⟨⟩_)
73+
hiding (step-≋; step-≋˘; _≋⟨⟩_)
7474

7575
------------------------------------------------------------------------
7676
-- Properties relating _⊆_ to various list functions

0 commit comments

Comments
 (0)