The Agda standard library has a few properties on how reverse
and _++_
work on List
. Trying to transfer these proofs to Vec
appears to be non-trivial (disregarding universes):
open import Data.Nat
open import Data.Vec
open import Relation.Binary.HeterogeneousEquality
unfold-reverse : {A : Set} → (x : A) → {n : ℕ} → (xs : Vec A n) →
reverse (x ∷ xs) ≅ reverse xs ++ [ x ]
TL;DR: How to prove unfold-reverse
?
The rest of this question outlines approaches to doing so and explains what problems surface.
The type of this property is very similar to the List
counter part in Data.List.Properties
. The proof involves a helper which roughly translates to:
open import Function
helper : ∀ {n m} → (xs : Vec A n) → (ys : Vec A m) →
foldl (Vec A ∘ (flip _+_ n)) (flip _∷_) xs ys ≅ reverse ys ++ xs
Trying to insert this helper in unfold-reverse
fails, because the left hand reverse
is a foldl
application with Vec A ∘ suc
as first argument whereas the left hand side of helper
has a foldl
application with Vec A ∘ (flip _+_ 1)
as first argument. Even though suc ≗ flip _+_ 1
is readily available from Data.Nat.Properties.Simple
, it cannot be used here as cong
would need a non-pointwise equality here and we don't have extensionality without further assumptions.
Removing the flip
from flip _+_ n
in helper
yields a type error, so that is no option either.
Any other ideas?
The
Data.Vec.Properties
module contains this function:Here is more or less elaborated solution:
Note, that only
B₁
andB₂
are distinct in the arguments of thefoldl-cong
function. After simplifying context in the hole we haveSo we need to prove, that at each recursive call adding an element to an accumulator of type
Vec A (n + 1)
is equal to adding an element to an accumulator of typeVec A (1 + n)
, and then results of twofoldl
s are equal. The proof itself is simple. Here is the whole code: