-
Notifications
You must be signed in to change notification settings - Fork 248
Add (propositional) equational reasoning combinators for vectors #2067
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
MatthewDaggitt
merged 20 commits into
agda:master
from
shhyou:vec-equational-reasoning-rebased
Oct 5, 2023
+502
−35
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
db26bb9
Add combinators for equational reasoning of vector
shhyou 48f12f4
review: rename module
shhyou 31f7917
review: wrap comments
shhyou da40fb8
review: only open CastReasoning locally
shhyou bef3328
Remove duplicate definition of cast-{is-id,trans}
shhyou 22a8d7e
review: use _≈[_]_ as the name of the equality
shhyou 4275945
review: remove extra parenthesis
shhyou eca0dfb
slightly cleanup the symmetric combinators
shhyou ce31244
Merge branch 'master' into vec-equational-reasoning-rebased
shhyou e11cbc5
Fixup of bef3328: cong _ refl is refl
shhyou db5c229
Add README for the library
shhyou ec17b45
Remove the syntax declaration of `_≈cong[_]_`
shhyou 38512c0
Merge branch 'master' into vec-equational-reasoning-rebased
shhyou 9da2ed3
delete git merge annotations
shhyou 47d0ff3
review: open ≡-Reasoning locally to avoid renaming CastReasoning
shhyou 01d7b1b
review: re-export cast-is-id and cast-trans
shhyou 90a124d
review: place reasoning combinators in a module
shhyou 1b7777d
cosmetic changes: fix README empty lines
shhyou 2be93c9
review: re-export ==-Reasoning
shhyou 7cb7559
Add pointers to the README before cast
shhyou File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
------------------------------------------------------------------------ | ||
-- The Agda standard library | ||
-- | ||
-- An equational reasoning library for propositional equality over | ||
-- vectors of different indices using cast. | ||
------------------------------------------------------------------------ | ||
|
||
{-# OPTIONS --cubical-compatible --safe #-} | ||
|
||
module README.Data.Vec.Relation.Binary.Equality.Cast where | ||
|
||
open import Agda.Primitive | ||
open import Data.List.Base as L using (List) | ||
import Data.List.Properties as Lₚ | ||
open import Data.Nat.Base | ||
open import Data.Nat.Properties | ||
open import Data.Vec.Base | ||
open import Data.Vec.Properties | ||
open import Data.Vec.Relation.Binary.Equality.Cast | ||
open import Relation.Binary.PropositionalEquality | ||
using (_≡_; refl; trans; sym; cong; subst; module ≡-Reasoning) | ||
|
||
private variable | ||
a : Level | ||
A : Set a | ||
l m n o : ℕ | ||
xs ys zs ws : Vec A n | ||
|
||
|
||
-- To see example usages of this library, scroll to the combinators | ||
-- section. | ||
|
||
|
||
------------------------------------------------------------------------ | ||
-- Motivation | ||
-- | ||
-- The `cast` function is the computational variant of `subst` for | ||
-- vectors. Since `cast` computes under vector constructors, it | ||
-- enables reasoning about vectors with non-definitionally equal indices | ||
-- by induction. See, e.g., Jacques Carette's comment in issue #1668. | ||
-- <https://github.com/agda/agda-stdlib/pull/1668#issuecomment-1003449509> | ||
-- | ||
-- Suppose we want to prove that ‘xs ++ [] ≡ xs’. Because `xs ++ []` | ||
-- has type `Vec A (n + 0)` while `xs` has type `Vec A n`, they cannot | ||
-- be directly related by homogeneous equality. | ||
-- To resolve the issue, `++-right-identity` uses `cast` to recast | ||
-- `xs ++ []` as a vector in `Vec A n`. | ||
-- | ||
++-right-identity : ∀ .(eq : n + 0 ≡ n) (xs : Vec A n) → cast eq (xs ++ []) ≡ xs | ||
++-right-identity eq [] = refl | ||
++-right-identity eq (x ∷ xs) = cong (x ∷_) (++-right-identity (cong pred eq) xs) | ||
-- | ||
-- When the input is `x ∷ xs`, because `cast eq (x ∷ _)` equals | ||
-- `x ∷ cast (cong pred eq) _`, the proof obligation | ||
-- cast eq (x ∷ xs ++ []) ≡ x ∷ xs | ||
-- simplifies to | ||
-- x :: cast (cong pred eq) (xs ++ []) ≡ x ∷ xs | ||
|
||
|
||
-- Although `cast` makes it possible to prove vector identities by ind- | ||
-- uction, the explicit type-casting nature poses a significant barrier | ||
-- to code reuse in larger proofs. For example, consider the identity | ||
-- ‘fromList (xs L.∷ʳ x) ≡ (fromList xs) ∷ʳ x’ where `L._∷ʳ_` is the | ||
-- snoc function of lists. We have | ||
-- | ||
-- fromList (xs L.∷ʳ x) : Vec A (L.length (xs L.∷ʳ x)) | ||
-- = {- by definition -} | ||
-- fromList (xs L.++ L.[ x ]) : Vec A (L.length (xs L.++ L.[ x ])) | ||
-- = {- by fromList-++ -} | ||
-- fromList xs ++ fromList L.[ x ] : Vec A (L.length xs + L.length [ x ]) | ||
-- = {- by definition -} | ||
-- fromList xs ++ [ x ] : Vec A (L.length xs + 1) | ||
-- = {- by unfold-∷ʳ -} | ||
-- fromList xs ∷ʳ x : Vec A (suc (L.length xs)) | ||
-- where | ||
-- fromList-++ : cast _ (fromList (xs L.++ ys)) ≡ fromList xs ++ fromList ys | ||
-- unfold-∷ʳ : cast _ (xs ∷ʳ x) ≡ xs ++ [ x ] | ||
-- | ||
-- Although the identity itself is simple, the reasoning process changes | ||
-- the index in the type twice. Consequently, its Agda translation must | ||
-- insert two `cast`s in the proof. Moreover, the proof first has to | ||
-- rearrange (the Agda version of) the identity into one with two | ||
-- `cast`s, resulting in lots of boilerplate code as demonstrated by | ||
-- `example1a-fromList-∷ʳ`. | ||
example1a-fromList-∷ʳ : ∀ (x : A) xs .(eq : L.length (xs L.∷ʳ x) ≡ suc (L.length xs)) → | ||
cast eq (fromList (xs L.∷ʳ x)) ≡ fromList xs ∷ʳ x | ||
example1a-fromList-∷ʳ x xs eq = begin | ||
cast eq (fromList (xs L.∷ʳ x)) ≡⟨⟩ | ||
cast eq (fromList (xs L.++ L.[ x ])) ≡˘⟨ cast-trans eq₁ eq₂ (fromList (xs L.++ L.[ x ])) ⟩ | ||
cast eq₂ (cast eq₁ (fromList (xs L.++ L.[ x ]))) ≡⟨ cong (cast eq₂) (fromList-++ xs) ⟩ | ||
cast eq₂ (fromList xs ++ [ x ]) ≡⟨ ≈-sym (unfold-∷ʳ (sym eq₂) x (fromList xs)) ⟩ | ||
fromList xs ∷ʳ x ∎ | ||
where | ||
open ≡-Reasoning | ||
eq₁ = Lₚ.length-++ xs {L.[ x ]} | ||
eq₂ = +-comm (L.length xs) 1 | ||
|
||
-- The `cast`s are irrelevant to core of the proof. At the same time, | ||
-- they can be inferred from the lemmas used during the reasoning steps | ||
-- (e.g. `fromList-++` and `unfold-∷ʳ`). To eliminate the boilerplate, | ||
-- this library provides a set of equational reasoning combinators for | ||
-- equality of the form `cast eq xs ≡ ys`. | ||
example1b-fromList-∷ʳ : ∀ (x : A) xs .(eq : L.length (xs L.∷ʳ x) ≡ suc (L.length xs)) → | ||
cast eq (fromList (xs L.∷ʳ x)) ≡ fromList xs ∷ʳ x | ||
example1b-fromList-∷ʳ x xs eq = begin | ||
fromList (xs L.∷ʳ x) ≈⟨⟩ | ||
fromList (xs L.++ L.[ x ]) ≈⟨ fromList-++ xs ⟩ | ||
fromList xs ++ [ x ] ≈˘⟨ unfold-∷ʳ (+-comm 1 (L.length xs)) x (fromList xs) ⟩ | ||
fromList xs ∷ʳ x ∎ | ||
where open CastReasoning | ||
|
||
|
||
------------------------------------------------------------------------ | ||
-- Combinators | ||
-- | ||
-- Let `xs ≈[ m≡n ] ys` denote `cast m≡n xs ≡ ys`. We have reflexivity, | ||
-- symmetry and transitivity: | ||
-- ≈-reflexive : xs ≈[ refl ] xs | ||
-- ≈-sym : xs ≈[ m≡n ] ys → ys ≈[ sym m≡n ] xs | ||
-- ≈-trans : xs ≈[ m≡n ] ys → ys ≈[ n≡o ] zs → xs ≈[ trans m≡n n≡o ] zs | ||
-- Accordingly, `_≈[_]_` admits the standard set of equational reasoning | ||
-- combinators. Suppose `≈-eqn : xs ≈[ m≡n ] ys`, | ||
-- xs ≈⟨ ≈-eqn ⟩ -- `_≈⟨_⟩_` takes a `_≈[_]_` step, adjusting | ||
-- ys -- the index at the same time | ||
-- | ||
-- ys ≈˘⟨ ≈-eqn ⟩ -- `_≈˘⟨_⟩_` takes a symmetric `_≈[_]_` step | ||
-- xs | ||
example2a : ∀ .(eq : suc m + n ≡ m + suc n) (xs : Vec A m) a ys → | ||
cast eq ((reverse xs ∷ʳ a) ++ ys) ≡ reverse xs ++ (a ∷ ys) | ||
example2a eq xs a ys = begin | ||
(reverse xs ∷ʳ a) ++ ys ≈⟨ ∷ʳ-++ eq a (reverse xs) ⟩ -- index: suc m + n | ||
reverse xs ++ (a ∷ ys) ∎ -- index: m + suc n | ||
where open CastReasoning | ||
|
||
-- To interoperate with `_≡_`, this library provides `_≂⟨_⟩_` (\-~) for | ||
-- taking a `_≡_` step during equational reasoning. | ||
-- Let `≡-eqn : xs ≡ ys`, then | ||
-- xs ≂⟨ ≡-eqn ⟩ -- Takes a `_≡_` step; no change to the index | ||
-- ys | ||
-- | ||
-- ys ≂˘⟨ ≡-eqn ⟩ -- Takes a symmetric `_≡_` step | ||
-- xs | ||
-- Equivalently, `≈-reflexive` injects `_≡_` into `_≈[_]_`. That is, | ||
-- `xs ≂⟨ ≡-eqn ⟩ ys` is the same as `xs ≈⟨ ≈-reflexive ≡-eqn ⟩ ys`. | ||
-- Extending `example2a`, we have: | ||
example2b : ∀ .(eq : suc m + n ≡ m + suc n) (xs : Vec A m) a ys → | ||
cast eq ((a ∷ xs) ʳ++ ys) ≡ xs ʳ++ (a ∷ ys) | ||
example2b eq xs a ys = begin | ||
(a ∷ xs) ʳ++ ys ≂⟨ unfold-ʳ++ (a ∷ xs) ys ⟩ -- index: suc m + n | ||
reverse (a ∷ xs) ++ ys ≂⟨ cong (_++ ys) (reverse-∷ a xs) ⟩ -- index: suc m + n | ||
(reverse xs ∷ʳ a) ++ ys ≈⟨ ∷ʳ-++ eq a (reverse xs) ⟩ -- index: suc m + n | ||
reverse xs ++ (a ∷ ys) ≂˘⟨ unfold-ʳ++ xs (a ∷ ys) ⟩ -- index: m + suc n | ||
xs ʳ++ (a ∷ ys) ∎ -- index: m + suc n | ||
where open CastReasoning | ||
|
||
-- Oftentimes index-changing identities apply to only part of the proof | ||
-- term. When reasoning about `_≡_`, `cong` shifts the focus to the | ||
-- subterm of interest. In this library, `≈-cong` does a similar job. | ||
-- Suppose `f : A → B`, `xs : B`, `ys zs : A`, `ys≈zs : ys ≈[ _ ] zs` | ||
-- and `xs≈f⟨c·ys⟩ : xs ≈[ _ ] f (cast _ ys)`, we have | ||
-- xs ≈⟨ ≈-cong f xs≈f⟨c·ys⟩ ys≈zs ⟩ | ||
-- f zs | ||
-- The reason for having the extra argument `xs≈f⟨c·ys⟩` is to expose | ||
-- `cast` in the subterm in order to apply the step `ys≈zs`. When using | ||
-- ordinary `cong` the proof has to explicitly push `cast` inside: | ||
-- xs ≈⟨ xs≈f⟨c·ys⟩ ⟩ | ||
-- f (cast _ ys) ≂⟨ cong f ys≈zs ⟩ | ||
-- f zs | ||
-- Note. Technically, `A` and `B` should be vectors of different length | ||
-- and that `ys`, `zs` are vectors of non-definitionally equal index. | ||
example3a-fromList-++-++ : {xs ys zs : List A} → | ||
.(eq : L.length (xs L.++ ys L.++ zs) ≡ | ||
L.length xs + (L.length ys + L.length zs)) → | ||
cast eq (fromList (xs L.++ ys L.++ zs)) ≡ | ||
fromList xs ++ fromList ys ++ fromList zs | ||
example3a-fromList-++-++ {xs = xs} {ys} {zs} eq = begin | ||
fromList (xs L.++ ys L.++ zs) ≈⟨ fromList-++ xs ⟩ | ||
fromList xs ++ fromList (ys L.++ zs) ≈⟨ ≈-cong (fromList xs ++_) (cast-++ʳ (Lₚ.length-++ ys) (fromList xs)) | ||
(fromList-++ ys) ⟩ | ||
fromList xs ++ fromList ys ++ fromList zs ∎ | ||
where open CastReasoning | ||
|
||
-- As an alternative, one can manually apply `cast-++ʳ` to expose `cast` | ||
-- in the subterm. However, this unavoidably duplicates the proof term. | ||
example3b-fromList-++-++′ : {xs ys zs : List A} → | ||
.(eq : L.length (xs L.++ ys L.++ zs) ≡ | ||
L.length xs + (L.length ys + L.length zs)) → | ||
cast eq (fromList (xs L.++ ys L.++ zs)) ≡ | ||
fromList xs ++ fromList ys ++ fromList zs | ||
example3b-fromList-++-++′ {xs = xs} {ys} {zs} eq = begin | ||
fromList (xs L.++ ys L.++ zs) ≈⟨ fromList-++ xs ⟩ | ||
fromList xs ++ fromList (ys L.++ zs) ≈⟨ cast-++ʳ (Lₚ.length-++ ys) (fromList xs) ⟩ | ||
fromList xs ++ cast _ (fromList (ys L.++ zs)) ≂⟨ cong (fromList xs ++_) (fromList-++ ys) ⟩ | ||
fromList xs ++ fromList ys ++ fromList zs ∎ | ||
where open CastReasoning | ||
|
||
-- `≈-cong` can be chained together much like how `cong` can be nested. | ||
-- In this example, `unfold-∷ʳ` is applied to the term `xs ++ [ a ]` | ||
-- in `(_++ ys)` inside of `reverse`. Thus the proof employs two | ||
-- `≈-cong`. | ||
example4-cong² : ∀ .(eq : (m + 1) + n ≡ n + suc m) a (xs : Vec A m) ys → | ||
cast eq (reverse ((xs ++ [ a ]) ++ ys)) ≡ ys ʳ++ reverse (xs ∷ʳ a) | ||
example4-cong² {m = m} {n} eq a xs ys = begin | ||
reverse ((xs ++ [ a ]) ++ ys) ≈˘⟨ ≈-cong reverse (cast-reverse (cong (_+ n) (+-comm 1 m)) ((xs ∷ʳ a) ++ ys)) | ||
(≈-cong (_++ ys) (cast-++ˡ (+-comm 1 m) (xs ∷ʳ a)) | ||
(unfold-∷ʳ _ a xs)) ⟩ | ||
reverse ((xs ∷ʳ a) ++ ys) ≈⟨ reverse-++ (+-comm (suc m) n) (xs ∷ʳ a) ys ⟩ | ||
reverse ys ++ reverse (xs ∷ʳ a) ≂˘⟨ unfold-ʳ++ ys (reverse (xs ∷ʳ a)) ⟩ | ||
ys ʳ++ reverse (xs ∷ʳ a) ∎ | ||
where open CastReasoning | ||
|
||
------------------------------------------------------------------------ | ||
-- Interoperation between `_≈[_]_` and `_≡_` | ||
-- | ||
-- This library is designed to interoperate with `_≡_`. Examples in the | ||
MatthewDaggitt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
-- combinators section showed how to apply `_≂⟨_⟩_` to take an `_≡_` | ||
-- step during equational reasoning about `_≈[_]_`. Recall that | ||
-- `xs ≈[ m≡n ] ys` is a shorthand for `cast m≡n xs ≡ ys`, the | ||
-- combinator is essentially the composition of `_≡_` on the left-hand | ||
-- side of `_≈[_]_`. Dually, the combinator `_≃⟨_⟩_` composes `_≡_` on | ||
-- the right-hand side of `_≈[_]_`. Thus `_≃⟨_⟩_` intuitively ends the | ||
-- reasoning system of `_≈[_]_` and switches back to the reasoning | ||
-- system of `_≡_`. | ||
example5-fromList-++-++′ : {xs ys zs : List A} → | ||
.(eq : L.length (xs L.++ ys L.++ zs) ≡ | ||
L.length xs + (L.length ys + L.length zs)) → | ||
cast eq (fromList (xs L.++ ys L.++ zs)) ≡ | ||
fromList xs ++ fromList ys ++ fromList zs | ||
example5-fromList-++-++′ {xs = xs} {ys} {zs} eq = begin | ||
fromList (xs L.++ ys L.++ zs) ≈⟨ fromList-++ xs ⟩ | ||
fromList xs ++ fromList (ys L.++ zs) ≃⟨ cast-++ʳ (Lₚ.length-++ ys) (fromList xs) ⟩ | ||
fromList xs ++ cast _ (fromList (ys L.++ zs)) ≡⟨ cong (fromList xs ++_) (fromList-++ ys) ⟩ | ||
fromList xs ++ fromList ys ++ fromList zs ≡-∎ | ||
where open CastReasoning | ||
|
||
-- Of course, it is possible to start with the reasoning system of `_≡_` | ||
-- and then switch to the reasoning system of `_≈[_]_`. | ||
example6a-reverse-∷ʳ : ∀ x (xs : Vec A n) → reverse (xs ∷ʳ x) ≡ x ∷ reverse xs | ||
example6a-reverse-∷ʳ {n = n} x xs = begin-≡ | ||
reverse (xs ∷ʳ x) ≡˘⟨ ≈-reflexive refl ⟩ | ||
reverse (xs ∷ʳ x) ≈⟨ ≈-cong reverse (cast-reverse _ _) (unfold-∷ʳ (+-comm 1 n) x xs) ⟩ | ||
reverse (xs ++ [ x ]) ≈⟨ reverse-++ (+-comm n 1) xs [ x ] ⟩ | ||
x ∷ reverse xs ∎ | ||
where open CastReasoning | ||
|
||
example6b-reverse-∷ʳ-by-induction : ∀ x (xs : Vec A n) → reverse (xs ∷ʳ x) ≡ x ∷ reverse xs | ||
example6b-reverse-∷ʳ-by-induction x [] = refl | ||
example6b-reverse-∷ʳ-by-induction x (y ∷ xs) = begin | ||
reverse (y ∷ (xs ∷ʳ x)) ≡⟨ reverse-∷ y (xs ∷ʳ x) ⟩ | ||
reverse (xs ∷ʳ x) ∷ʳ y ≡⟨ cong (_∷ʳ y) (example6b-reverse-∷ʳ-by-induction x xs) ⟩ | ||
(x ∷ reverse xs) ∷ʳ y ≡⟨⟩ | ||
x ∷ (reverse xs ∷ʳ y) ≡˘⟨ cong (x ∷_) (reverse-∷ y xs) ⟩ | ||
x ∷ reverse (y ∷ xs) ∎ | ||
where open ≡-Reasoning |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
------------------------------------------------------------------------ | ||
-- The Agda standard library | ||
-- | ||
-- An equational reasoning library for propositional equality over | ||
-- vectors of different indices using cast. | ||
-- | ||
-- See README.Data.Vec.Relation.Binary.Equality.Cast for | ||
shhyou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
-- documentation and examples. | ||
------------------------------------------------------------------------ | ||
|
||
{-# OPTIONS --cubical-compatible --safe #-} | ||
|
||
module Data.Vec.Relation.Binary.Equality.Cast {a} {A : Set a} where | ||
|
||
open import Data.Nat.Base using (ℕ; zero; suc) | ||
open import Data.Nat.Properties using (suc-injective) | ||
open import Data.Vec.Base | ||
open import Relation.Binary.Core using (REL; _⇒_) | ||
open import Relation.Binary.Definitions using (Sym; Trans) | ||
open import Relation.Binary.PropositionalEquality.Core | ||
using (_≡_; refl; trans; sym; cong; module ≡-Reasoning) | ||
|
||
private | ||
variable | ||
l m n o : ℕ | ||
xs ys zs : Vec A n | ||
|
||
|
||
cast-is-id : .(eq : m ≡ m) (xs : Vec A m) → cast eq xs ≡ xs | ||
cast-is-id eq [] = refl | ||
cast-is-id eq (x ∷ xs) = cong (x ∷_) (cast-is-id (suc-injective eq) xs) | ||
|
||
cast-trans : .(eq₁ : m ≡ n) .(eq₂ : n ≡ o) (xs : Vec A m) → | ||
cast eq₂ (cast eq₁ xs) ≡ cast (trans eq₁ eq₂) xs | ||
cast-trans {m = zero} {n = zero} {o = zero} eq₁ eq₂ [] = refl | ||
cast-trans {m = suc _} {n = suc _} {o = suc _} eq₁ eq₂ (x ∷ xs) = | ||
cong (x ∷_) (cast-trans (suc-injective eq₁) (suc-injective eq₂) xs) | ||
|
||
|
||
infix 3 _≈[_]_ | ||
|
||
_≈[_]_ : ∀ {n m} → Vec A n → .(eq : n ≡ m) → Vec A m → Set a | ||
xs ≈[ eq ] ys = cast eq xs ≡ ys | ||
|
||
------------------------------------------------------------------------ | ||
-- _≈[_]_ is ‘reflexive’, ‘symmetric’ and ‘transitive’ | ||
|
||
≈-reflexive : ∀ {n} → _≡_ ⇒ (λ xs ys → _≈[_]_ {n} xs refl ys) | ||
≈-reflexive {x = x} eq = trans (cast-is-id refl x) eq | ||
|
||
≈-sym : .{m≡n : m ≡ n} → Sym _≈[ m≡n ]_ _≈[ sym m≡n ]_ | ||
≈-sym {m≡n = m≡n} {xs} {ys} xs≈ys = begin | ||
cast (sym m≡n) ys ≡˘⟨ cong (cast (sym m≡n)) xs≈ys ⟩ | ||
cast (sym m≡n) (cast m≡n xs) ≡⟨ cast-trans m≡n (sym m≡n) xs ⟩ | ||
cast (trans m≡n (sym m≡n)) xs ≡⟨ cast-is-id (trans m≡n (sym m≡n)) xs ⟩ | ||
xs ∎ | ||
where open ≡-Reasoning | ||
|
||
≈-trans : ∀ .{m≡n : m ≡ n} .{n≡o : n ≡ o} → Trans _≈[ m≡n ]_ _≈[ n≡o ]_ _≈[ trans m≡n n≡o ]_ | ||
≈-trans {m≡n = m≡n} {n≡o} {xs} {ys} {zs} xs≈ys ys≈zs = begin | ||
cast (trans m≡n n≡o) xs ≡˘⟨ cast-trans m≡n n≡o xs ⟩ | ||
cast n≡o (cast m≡n xs) ≡⟨ cong (cast n≡o) xs≈ys ⟩ | ||
cast n≡o ys ≡⟨ ys≈zs ⟩ | ||
zs ∎ | ||
where open ≡-Reasoning | ||
|
||
------------------------------------------------------------------------ | ||
-- Reasoning combinators | ||
|
||
module CastReasoning where | ||
|
||
open ≡-Reasoning public | ||
renaming (begin_ to begin-≡_; _∎ to _≡-∎) | ||
|
||
begin_ : ∀ .{m≡n : m ≡ n} {xs : Vec A m} {ys} → xs ≈[ m≡n ] ys → cast m≡n xs ≡ ys | ||
begin xs≈ys = xs≈ys | ||
|
||
_∎ : (xs : Vec A n) → cast refl xs ≡ xs | ||
_∎ xs = ≈-reflexive refl | ||
|
||
_≈⟨⟩_ : ∀ .{m≡n : m ≡ n} (xs : Vec A m) {ys} → xs ≈[ m≡n ] ys → xs ≈[ m≡n ] ys | ||
xs ≈⟨⟩ xs≈ys = xs≈ys | ||
|
||
-- composition of _≈[_]_ | ||
step-≈ : ∀ .{m≡n : m ≡ n}.{m≡o : m ≡ o} (xs : Vec A m) {ys : Vec A n} {zs : Vec A o} → | ||
ys ≈[ trans (sym m≡n) m≡o ] zs → xs ≈[ m≡n ] ys → xs ≈[ m≡o ] zs | ||
step-≈ xs ys≈zs xs≈ys = ≈-trans xs≈ys ys≈zs | ||
|
||
-- composition of the equality type on the right-hand side of _≈[_]_, | ||
-- or escaping to ordinary _≡_ | ||
step-≃ : ∀ .{m≡n : m ≡ n} (xs : Vec A m) {ys zs} → ys ≡ zs → xs ≈[ m≡n ] ys → xs ≈[ m≡n ] zs | ||
step-≃ xs ys≡zs xs≈ys = ≈-trans xs≈ys (≈-reflexive ys≡zs) | ||
|
||
-- composition of the equality type on the left-hand side of _≈[_]_ | ||
step-≂ : ∀ .{m≡n : m ≡ n} (xs : Vec A m) {ys zs} → ys ≈[ m≡n ] zs → xs ≡ ys → xs ≈[ m≡n ] zs | ||
step-≂ xs ys≈zs xs≡ys = ≈-trans (≈-reflexive xs≡ys) ys≈zs | ||
|
||
-- `cong` after a `_≈[_]_` step that exposes the `cast` to the `cong` | ||
-- operation | ||
≈-cong : ∀ .{l≡o : l ≡ o} .{m≡n : m ≡ n} {xs : Vec A m} {ys zs} (f : Vec A o → Vec A n) → | ||
xs ≈[ m≡n ] f (cast l≡o ys) → ys ≈[ l≡o ] zs → xs ≈[ m≡n ] f zs | ||
≈-cong f xs≈fys ys≈zs = trans xs≈fys (cong f ys≈zs) | ||
|
||
|
||
-- symmetric version of each of the operator | ||
step-≈˘ : ∀ .{n≡m : n ≡ m}.{m≡o : m ≡ o} (xs : Vec A m) {ys : Vec A n} {zs : Vec A o} → | ||
ys ≈[ trans n≡m m≡o ] zs → ys ≈[ n≡m ] xs → xs ≈[ m≡o ] zs | ||
step-≈˘ xs ys≈zs ys≈xs = step-≈ xs ys≈zs (≈-sym ys≈xs) | ||
|
||
step-≃˘ : ∀ .{m≡n : m ≡ n} (xs : Vec A m) {ys zs} → ys ≡ zs → ys ≈[ sym m≡n ] xs → xs ≈[ m≡n ] zs | ||
step-≃˘ xs ys≡zs ys≈xs = step-≃ xs ys≡zs (≈-sym ys≈xs) | ||
|
||
step-≂˘ : ∀ .{m≡n : m ≡ n} (xs : Vec A m) {ys zs} → ys ≈[ m≡n ] zs → ys ≡ xs → xs ≈[ m≡n ] zs | ||
step-≂˘ xs ys≈zs ys≡xs = step-≂ xs ys≈zs (sym ys≡xs) | ||
|
||
|
||
------------------------------------------------------------------------ | ||
-- convenient syntax for ‘equational’ reasoning | ||
|
||
infix 1 begin_ | ||
infixr 2 step-≃ step-≂ step-≃˘ step-≂˘ step-≈ step-≈˘ _≈⟨⟩_ ≈-cong | ||
infix 3 _∎ | ||
|
||
syntax step-≃ xs ys≡zs xs≈ys = xs ≃⟨ xs≈ys ⟩ ys≡zs | ||
syntax step-≃˘ xs ys≡zs xs≈ys = xs ≃˘⟨ xs≈ys ⟩ ys≡zs | ||
syntax step-≂ xs ys≈zs xs≡ys = xs ≂⟨ xs≡ys ⟩ ys≈zs | ||
syntax step-≂˘ xs ys≈zs ys≡xs = xs ≂˘⟨ ys≡xs ⟩ ys≈zs | ||
syntax step-≈ xs ys≈zs xs≈ys = xs ≈⟨ xs≈ys ⟩ ys≈zs | ||
syntax step-≈˘ xs ys≈zs ys≈xs = xs ≈˘⟨ ys≈xs ⟩ ys≈zs |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.