Skip to content

Commit 69bbe51

Browse files
authored
Another tweak to cong! (#2340)
* Disallow meta variables in goals - they break anti-unification. * Postpone checking for metas. * CHANGELOG entry, unit tests, code tweak. * Move blockOnMetas to a new Reflection.TCM.Utilities module.
1 parent e48213e commit 69bbe51

File tree

4 files changed

+96
-9
lines changed

4 files changed

+96
-9
lines changed

CHANGELOG.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -458,5 +458,7 @@ Additions to existing modules
458458
WeaklyDecidable : Pred A ℓ → Set _
459459
```
460460

461-
* `Tactic.Cong` now provides a marker function, `⌞_⌟`, for user-guided
462-
anti-unification. See README.Tactic.Cong for details.
461+
* Enhancements to `Tactic.Cong` - see `README.Tactic.Cong` for details.
462+
- Provide a marker function, `⌞_⌟`, for user-guided anti-unification.
463+
- Improved support for equalities between terms with instance arguments,
464+
such as terms that contain `_/_` or `_%_`.

doc/README/Tactic/Cong.agda

+33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
module README.Tactic.Cong where
44

55
open import Data.Nat
6+
open import Data.Nat.DivMod
67
open import Data.Nat.Properties
78

89
open import Relation.Binary.PropositionalEquality
@@ -161,3 +162,35 @@ module EquationalReasoningTests where
161162
≤⟨ n≤1+n _ ⟩
162163
suc (suc (n + n))
163164
165+
166+
module MetaTests where
167+
168+
test₁ : ∀ m n o → .⦃ _ : NonZero o ⦄ (m + n) / o ≡ (n + m) / o
169+
test₁ m n o =
170+
let open ≤-Reasoning in
171+
begin-equality
172+
⌞ m + n ⌟ / o
173+
≡⟨ cong! (+-comm m n) ⟩
174+
(n + m) / o
175+
176+
177+
test₂ : ∀ m n o p q r → .⦃ _ : NonZero o ⦄ → .⦃ _ : NonZero p ⦄
178+
.⦃ _ : NonZero q ⦄ p ≡ q ^ r (m + n) % o % p ≡ (n + m) % o % p
179+
test₂ m n o p q r eq =
180+
let
181+
open ≤-Reasoning
182+
instance q^r≢0 = m^n≢0 q r
183+
in
184+
begin-equality
185+
(m + n) % o % p
186+
≡⟨ %-congʳ eq ⟩
187+
⌞ m + n ⌟ % o % q ^ r
188+
≡⟨ cong! (+-comm m n) ⟩
189+
⌞ n + m ⌟ % o % q ^ r
190+
≡⟨ cong! (+-comm m n) ⟨
191+
⌞ m + n ⌟ % o % q ^ r
192+
≡⟨ cong! (+-comm m n) ⟩
193+
(n + m) % o % q ^ r
194+
≡⟨ %-congʳ eq ⟨
195+
(n + m) % o % p
196+

src/Reflection/TCM/Utilities.agda

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Reflection utilities
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --cubical-compatible --safe #-}
8+
9+
module Reflection.TCM.Utilities where
10+
11+
open import Data.List using (List; []; _∷_; _++_; map)
12+
open import Data.Unit using (⊤; tt)
13+
open import Effect.Applicative using (RawApplicative; mkRawApplicative)
14+
open import Function using (case_of_)
15+
open import Reflection.AST.Meta using (Meta)
16+
open import Reflection.AST.Term using (Term)
17+
open import Reflection.TCM using (TC; pure; blockTC; blockerAll; blockerMeta)
18+
19+
import Reflection.AST.Traversal as Traversal
20+
21+
blockOnMetas : Term TC ⊤
22+
blockOnMetas t =
23+
case traverseTerm actions (0 , []) t of λ where
24+
[] pure tt
25+
xs@(_ ∷ _) blockTC (blockerAll (map blockerMeta xs))
26+
where
27+
applicative : {ℓ} RawApplicative {ℓ} (λ _ List Meta)
28+
applicative = mkRawApplicative (λ _ List Meta) (λ _ []) _++_
29+
30+
open Traversal applicative
31+
32+
actions : Actions
33+
actions = record defaultActions { onMeta = λ _ x x ∷ [] }

src/Tactic/Cong.agda

+26-7
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ open import Data.Nat.Base as ℕ using (ℕ; zero; suc; _≡ᵇ_; _+_)
3737
open import Data.Unit.Base using (⊤)
3838
open import Data.Word.Base as Word using (toℕ)
3939
open import Data.Product.Base using (_×_; map₁; _,_)
40+
open import Function using (flip; case_of_)
4041

4142
open import Relation.Binary.PropositionalEquality.Core using (_≡_; refl; cong)
43+
open import Relation.Nullary.Decidable.Core using (yes; no)
4244

4345
-- 'Data.String.Properties' defines this via 'Dec', so let's use the
4446
-- builtin for maximum speed.
@@ -54,8 +56,10 @@ open import Reflection.AST.Literal as Literal
5456
open import Reflection.AST.Meta as Meta
5557
open import Reflection.AST.Name as Name
5658
open import Reflection.AST.Term as Term
59+
import Reflection.AST.Traversal as Traversal
5760

5861
open import Reflection.TCM.Syntax
62+
open import Reflection.TCM.Utilities
5963

6064
-- Marker to keep anti-unification from descending into the wrapped
6165
-- subterm.
@@ -102,6 +106,16 @@ private
102106
notEqualityError : {A : Set} Term TC A
103107
notEqualityError goal = typeError (strErr "Cannot rewrite a goal that is not equality: " ∷ termErr goal ∷ [])
104108

109+
unificationError : {A : Set} TC Term TC Term TC A
110+
unificationError term symTerm = do
111+
term' term
112+
symTerm' symTerm
113+
-- Don't show the same term twice.
114+
let symErr = case term' Term.≟ symTerm' of λ where
115+
(yes _) []
116+
(no _) strErr "\n" ∷ termErr symTerm' ∷ []
117+
typeError (strErr "cong! failed, tried:\n" ∷ termErr term' ∷ symErr)
118+
105119
record EqualityGoal : Set where
106120
constructor equals
107121
field
@@ -236,12 +250,17 @@ macro
236250
withNormalisation false $ do
237251
goal inferType hole
238252
eqGoal destructEqualityGoal goal
239-
let uni = λ lhs rhs do
240-
let cong-lam = antiUnify 0 lhs rhs
241-
cong-tm `cong eqGoal cong-lam x≡y
242-
unify cong-tm hole
253+
let makeTerm = λ lhs rhs `cong eqGoal (antiUnify 0 lhs rhs) x≡y
243254
let lhs = EqualityGoal.lhs eqGoal
244255
let rhs = EqualityGoal.rhs eqGoal
245-
-- When using ⌞_⌟ with ≡⟨ ... ⟨, (uni lhs rhs) fails and
246-
-- (uni rhs lhs) succeeds.
247-
catchTC (uni lhs rhs) (uni rhs lhs)
256+
let term = makeTerm lhs rhs
257+
let symTerm = makeTerm rhs lhs
258+
let uni = _>>= flip unify hole
259+
-- When using ⌞_⌟ with ≡⟨ ... ⟨, (uni term) fails and
260+
-- (uni symTerm) succeeds.
261+
catchTC (uni term) $
262+
catchTC (uni symTerm) $ do
263+
-- If we failed because of unresolved metas, restart.
264+
blockOnMetas goal
265+
-- If we failed for a different reason, show an error.
266+
unificationError term symTerm

0 commit comments

Comments
 (0)