S ys info:idris中列表上的简单等式证明(证明xs++ [x] = ys++ [y]->x= y->xs= ys)

关于S ys info的问题,在prooving中经常遇到, 我正在学习 idris,并且对证明列表的属性非常感兴趣。

我正在学习 idris,并且对证明列表的属性非常感兴趣。

如果你看一下standard library,有一个证明“两个列表是相等的,如果他们的头是相等的,他们的尾巴是相等的”。

consCong2 : {x : a} -> {xs : List a} -> {y : b} -> {ys : List b} ->
x = y -> xs = ys -> x :: xs = y :: ys
consCong2 Refl Refl = Refl

我们也可以证明另一个方向

consCong2' : {x : a} -> {xs : List a} -> {y : b} -> {ys : List b} ->
x::xs = y::ys -> x = y -> xs = ys
consCong2' Refl Refl = Refl

或者更明确地说,我们可以把方程两边的头都放下来得到证明。

consCong2' : {x : a} -> {xs : List a} -> {y : b} -> {ys : List b} ->
x::xs = y::ys -> x = y -> xs = ys
consCong2' prf_cons Refl = (cong {f = drop 1} prf_cons)

这将是有趣的,看看这些属性是否可以被证明也为最后一个项目在休息之前的一切。证明“两个列表是平等的,如果第一部分和最后一个项目是平等的”原来是很容易的

consCong2' : {x : a} -> {xs : List a} -> {y : b} -> {ys : List b} ->
x = y -> xs = ys -> xs ++ [x] = ys ++ [y]
consCong2' Refl Refl = Refl

但另一个方向失败的类型检查:

consCong2' : {x : a} -> {xs : List a} -> {y : b} -> {ys : List b} ->
xs ++ [x] = ys ++ [y] -> x = y -> xs = ys
consCong2' Refl Refl = Refl

因为

Type mismatch between
                         ys ++ [x]
                 and
                         xs ++ [x]

显然,因为如果xs ++ [x] = ys ++ [y]在演绎中排名第一,idris 不可能统一双方。

因此,我们需要做的就是告诉 idris 在等式的两边应用init,就像我们之前对drop 1所做的那样。这失败了,因为 init 需要证明列表非空,这在这里无法隐式推断。为此,我写了一个辅助函数,它明确定义了(a ++ [x]) = a

dropOneRight :  (xs : List a) -> List a
dropOneRight xs with (snocList xs)
  dropOneRight [] | Empty = []
  dropOneRight (a ++ [x]) | Snoc rec = a
consCong2' : {x : a} -> {xs : List a} -> {y : b} -> {ys : List b} ->
xs ++ [x] = ys ++ [y] -> x = y -> xs = ys
consCong2' prf_cons Refl = cong {f = dropOneRight} prf_cons

但这产生了

Type mismatch between
                 dropOneRight (ys ++ [x])
         and
                 ys

我在其他方法上花费了一些时间,使用snocList进行大小写拆分,但无法获得显着进展。我不明白如何向 idris 显示dropOneRight (ys ++ [x]) = ys。我如何证明xs ++ [x] = ys ++ [y] -> x = y -> xs = ys?

1

我想snocList方法将是棘手的;至少使用简单的证明策略来遵循定义。证明ys = dropOneRight (ys ++ [x])统一snocList (ys ++ [x])与参数将导致麻烦,大致:

prf' : (ys : List a) -> (x : a) -> ys = dropOneRight (ys ++ [x])
prf' ys x with (snocList (ys ++ [x]))
    ...
    prf' ?? x | Snoc rec = ?hole

如果你允许dropOneRight更简单,它是相当直接的:

dropOneRight : (xs : List a) -> List a
dropOneRight [] = []
dropOneRight [x] = []
dropOneRight (x :: y :: xs) = x :: dropOneRight (y :: xs)
dropPrf : (ys : List a) -> (x : a) -> ys = dropOneRight (ys ++ [x])
dropPrf [] z = Refl
dropPrf [x] z = Refl
dropPrf (x :: y :: xs) z = cong $ dropPrf (y::xs) z
consCong2' : {x : a} -> {xs : List a} -> {y : b} -> {ys : List b} ->
             xs ++ [x] = ys ++ [y] -> x = y -> xs = ys
consCong2' {xs} {ys} {x} prf_cons Refl = 
  rewrite dropPrf ys x in rewrite dropPrf xs x in
  cong prf_cons

本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处

(740)
Crawlers:PythonWebCrawlers和“获取”html源代码
上一篇
初学c语言用什么编程软件:为什么Node.js是用 C/C++编程语言编写的
下一篇

相关推荐

发表评论

登录 后才能评论

评论列表(67条)