Idris简单证明与列表

时间:2016-09-24 04:34:16

标签: idris theorem-proving

我试图用idris来证明一些简单的事情,但我却悲惨地失败了。这是我的代码

module MyReverse
%hide reverse
%default total

reverse : List a -> List a
reverse [] = []
reverse (x :: xs) = reverse xs ++ [x]

listEmptyAppend : (l : List a) -> [] ++ l = l
listEmptyAppend [] = Refl
listEmptyAppend (x :: xs) = Refl
listAppendEmpty : (l : List a) -> l ++ [] = l
listAppendEmpty [] = Refl
listAppendEmpty (x :: xs) = rewrite listAppendEmpty xs in Refl

list_append_eq : (l, l1, l2 : List a) -> l ++ l1 = l ++ l2 -> l1 = l2
list_append_eq l [] [] prf = Refl
list_append_eq l [] (x :: xs) prf = ?list_append_eq_rhs_1
list_append_eq l (x :: xs) [] prf = ?list_append_eq_rhs_2
list_append_eq l (x :: xs) (y :: ys) prf = ?list_append_eq_rhs_3

?list_append_eq_rhs_1的目标是(在几个intro'之后)

----------              Assumptions:              ----------
 a : Type
 l : List a
 x : a
 xs : List a
 prf : l ++ [] = l ++ x :: xs
----------                 Goal:                  ----------
{hole0} : [] = x :: xs

我想要做的是使用我已经证明的琐碎定理重写prf,直到它完全是目标,但我不知道如何在idris中做到这一点。

1 个答案:

答案 0 :(得分:4)

首先,我们需要::是单射的事实:

consInjective : {x : a} -> {l1, l2 : List a} -> x :: l1 = x :: l2 -> l1 = l2
consInjective Refl = Refl

然后我们可以使用上述事实通过list_append_eq上的归纳来证明l

list_append_eq : (l, l1, l2 : List a) -> l ++ l1 = l ++ l2 -> l1 = l2
list_append_eq [] _ _ prf = prf
list_append_eq (x :: xs) l1 l2 prf =
  list_append_eq xs l1 l2 (consInjective prf)

<小时/> 以下是@AndrásKovács建议的更简洁的版本,通过使用标准consInjective(同余)引理

,在没有cong的情况下获得相同的结果
Idris> :t cong
cong : (a = b) -> f a = f b

drop函数:

list_append_eq : (l, l1, l2 : List a) -> l ++ l1 = l ++ l2 -> l1 = l2
list_append_eq [] _ _ prf = prf
list_append_eq (x :: xs) l1 l2 prf =
  list_append_eq xs l1 l2 (cong {f = drop 1} prf)