Agda标准库有一些关于reverse
和_++_
如何处理List
的属性。试图将这些证据转移到Vec
似乎是非平凡的(无视宇宙):
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:如何证明unfold-reverse
?
本问题的其余部分概述了这样做的方法并解释了哪些问题浮出水面。
此属性的类型与List
中的Data.List.Properties
计数器部分非常相似。证据涉及帮助者,大致翻译为:
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
尝试在unfold-reverse
中插入此帮助程序失败,因为左侧reverse
是foldl
应用程序,Vec A ∘ suc
作为第一个参数,而helper
的左侧是{{ 1}}有foldl
个应用程序,Vec A ∘ (flip _+_ 1)
作为第一个参数。尽管suc ≗ flip _+_ 1
可以随时使用Data.Nat.Properties.Simple
,但由于此处cong
需要非逐点相等而无需进一步假设,因此我们无法使用flip
。
从flip _+_ n
中的helper
移除{{1}}会产生类型错误,因此也无法选择。
还有其他想法吗?
答案 0 :(得分:2)
Data.Vec.Properties
模块包含此功能:
foldl-cong : ∀ {a b} {A : Set a}
{B₁ : ℕ → Set b}
{f₁ : ∀ {n} → B₁ n → A → B₁ (suc n)} {e₁}
{B₂ : ℕ → Set b}
{f₂ : ∀ {n} → B₂ n → A → B₂ (suc n)} {e₂} →
(∀ {n x} {y₁ : B₁ n} {y₂ : B₂ n} →
y₁ ≅ y₂ → f₁ y₁ x ≅ f₂ y₂ x) →
e₁ ≅ e₂ →
∀ {n} (xs : Vec A n) →
foldl B₁ f₁ e₁ xs ≅ foldl B₂ f₂ e₂ xs
foldl-cong _ e₁=e₂ [] = e₁=e₂
foldl-cong {B₁ = B₁} f₁=f₂ e₁=e₂ (x ∷ xs) =
foldl-cong {B₁ = B₁ ∘ suc} f₁=f₂ (f₁=f₂ e₁=e₂) xs
这或多或少都是详细解决方案:
unfold-reverse : {A : Set} → (x : A) → {n : ℕ} → (xs : Vec A n) →
reverse (x ∷ xs) ≅ reverse xs ++ (x ∷ [])
unfold-reverse x xs = begin
foldl (Vec _ ∘ _+_ 1) (flip _∷_) (x ∷ []) xs
≅⟨ (foldl-cong
{B₁ = Vec _ ∘ _+_ 1}
{f₁ = flip _∷_}
{e₁ = x ∷ []}
{B₂ = Vec _ ∘ flip _+_ 1}
{f₂ = flip _∷_}
{e₂ = x ∷ []}
(λ {n} {a} {as₁} {as₂} as₁≅as₂ -> {!!})
refl
xs) ⟩
foldl (Vec _ ∘ flip _+_ 1) (flip _∷_) (x ∷ []) xs
≅⟨ helper (x ∷ []) xs ⟩
reverse xs ++ x ∷ []
∎
请注意,B₁
函数的参数中只有B₂
和foldl-cong
不同。在简化了洞中的上下文之后我们
Goal: a ∷ as₁ ≅ a ∷ as₂
————————————————————————————————————————————————————————————
as₁≅as₂ : as₁ ≅ as₂
as₂ : Vec A (n + 1)
as₁ : Vec A (1 + n)
a : A
n : ℕ
A : Set
所以我们需要证明,在每次递归调用时,向Vec A (n + 1)
类型的累加器添加一个元素等于将一个元素添加到类型为Vec A (1 + n)
的累加器中,然后将结果添加到两个{ {1}}是平等的。证明本身很简单。这是完整的代码:
foldl