我在锻炼身体。这似乎是一件微不足道的事情(简化以显示问题显然在列表拆分中):
infixr 4 _::_ _++_ _==_
data _==_ {A : Set} : (x : A) -> (y : A) -> Set where
refl : (x : A) -> x == x
data List (A : Set) : Set where
nil : List A
_::_ : A -> List A -> List A
_++_ : forall {A} -> List A -> List A -> List A
nil ++ ys = ys
(x :: xs) ++ ys = x :: (xs ++ ys)
data Permutation {A : Set} : List A -> List A -> Set where
pnil : Permutation nil nil
p:: : forall {xs} -> (x : A) ->
(zs : List A) -> (y : A) -> (ys : List A) ->
x == y -> Permutation xs (zs ++ ys) ->
Permutation (x :: xs) (zs ++ (y :: ys))
lemma-ripTop : forall {A} -> (xs : List A) ->
(y : A) -> (ys : List A) ->
Permutation xs (y :: ys) ->
Permutation xs (y :: ys)
lemma-ripTop nil y ys ()
lemma-ripTop (x :: xs) y ys (p:: .x zs y1 ys1 x==y1 ps) =
p:: x zs y1 ys1 x==y1 ps
长短不一,我声明可以定义两个列表的排列,如果它们可以提供Permutation
个较小的列表,其中包含一对相等的元素x
和{{1} } y
的插入位置由y
和zs
确定。
然后ys
(意味着做一些完全不同的事情,但这里lemma-ripTop
只是id
)需要证明给出Permutation
列表的内容( Permutation
)。
我无法理解为什么Agda需要看y :: ys
(这是我得到的错误) - 我认为这应该从类型声明和构造函数中清楚地看出来?即由于在输入时提供了zs ++ (y1 :: ys1) == y :: ys
,因此在构造函数Permutation xs (y :: ys)
中作为见证提供的拆分应该加起来为p::
。
如何说服Agda这个列表的拆分有效?
错误讯息:
y :: ys
答案 0 :(得分:1)
考虑以下片段(您可能知道这是身份类型/命题相等的归纳原则):
J : {A : Set} (P : (x y : A) → x == y → Set)
(f : ∀ x → P x x (refl x)) (x y : A) (p : x == y) → P x y p
J P f x y p = ?
当我们在p
上模式匹配并将其替换为refl
时:
J P f x y (refl .x) = ?
阿格达会喊出那个
x != y of type A
when checking that the pattern refl .x has type x == y
这是因为x
和y
不再是任意模式:p
上的模式匹配揭示了这两者之间的关系。也就是说,x
和y
必须是同一个东西。你必须写这个:
J P f x .x (refl .x) = f x
或许更好的例子是自然数的奇偶校验视图:
data Parity : ℕ → Set where
even : ∀ k → Parity (k * 2)
odd : ∀ k → Parity (1 + k * 2)
我们可以计算每个自然数的奇偶校验:
parity : ∀ n → Parity n
parity 0 = even 0
parity (suc n) with parity n
parity (suc .(k * 2)) | even k = odd k
parity (suc .(1 + k * 2)) | odd k = even (1 + k)
请注意,在模式匹配后,n
不再是任意的 - 它必须是k * 2
(如果是even
)或1 + k * 2
(如果是{{}} 1}})。
现在,让我们看看代码的问题在哪里。当您在置换参数上进行模式匹配时,odd
和y
会变得固定 - 模式会显示其结构,就像上面的情况一样。所以你实际上已经重写了ys
和y
来表达它们不再是任意的事实。但问题出在这里:如果你试着写下ys
和y
的外观,你会发现你不能这样做。 ys
可以是y
的第一个元素,也可以是zs
,具体取决于y1
。
zs
lemma-ripTop (x :: xs) .z .(zs ++ y1 :: ys1)
(p:: .x (z :: zs) y1 ys1 x==y1 ps) = ?
上的模式匹配不幸无效。整个(虚线)模式应该是zs
,但是在这里它被分成两个单独的模式,我想这是一个禁忌(不能说它是Agda不能做或不做的事,抱歉)
一种选择是将所有内容都移到校样中,我不确定它对你的情况有多大帮助,但是你走了。
首先,我们需要表达存在量化。依赖对(sigma类型)就是这样做的;这是标准库的定义:
z :: zs ++ y1 :: ys1
因此,例如,声明“存在一个自然数record Σ {a b} (A : Set a) (B : A → Set b) : Set (a ⊔ b) where
constructor _,_
field
proj₁ : A
proj₂ : B proj₁
open Σ public
,n
”将表示为n * n == 4
,证明将是一对自然数和证明它的正方形确实是4.在我们的例子中,这将是Σ ℕ λ n → n * n == 4
。
我们可以将(2 , refl 4)
拆分为l
这一事实将通过zs ++ ys
和r₁
的证据来表示,以便r₂
和最终的排列是l == r₁ ++ r₂
,然后我们需要证明k
。这就是整个事情:
k == r₁ ++ y :: r₂
这可能会或可能不会令人愉快,但它始终忠实于您的原始实现。如果您愿意使用其他内容:您可以使用辅助数据类型表示data Permutation {A : Set} : (xs ys : List A) → Set a where
nil : Permutation nil nil
cons : (x y : A) (xs ys zs : List A)
(p₁ : Σ _ λ r₁ → Σ _ λ r₂ → ys == r₁ ++ r₂)
(p₂ : x == y)
(p₃ : let (r₁ , r₂ , _) = p₁ in zs == r₁ ++ y :: r₂) →
Permutation xs ys → Permutation (x :: xs) zs
位于x
的某个位置:
xs
然后是排列:
data insert_into_==_ {A : Set} (x : A) : List A → List A → Set where
here : ∀ {xs} → insert x into xs == (x :: xs)
there : ∀ {y} {xs} {xys} → insert x into xs == xys →
insert x into (y :: xs) == (y :: xys)