我在代码中经常使用Vect数据类型。通常,我发现自己不得不证明一些涉及使用foldr的Vects上的库函数的事情。由于foldr是在foldrImpl之上实现的,因此如果我尝试通过在目标中出现的漏洞来检查证明上下文。我的问题是,idris似乎无法评估目标类型中的foldrImpl(与总体检查器不知道某个函数的总和类似),这使我陷入了证明。
通常,我对这个问题的解决方案是定义我自己的库函数版本,该函数从头开始折叠。但这显然不方便,因为:(i)我必须对库中已经存在的函数进行编码; (ii)这使我不会在以后打算证明的任何定义中使用折叠。
举一个具体的例子,请考虑我要证明以下内容
lemma_take_head : {x : a} ->
{xs : List a} ->
{ls : Vect len (List a)} ->
concat ((x :: xs) :: ls) = x :: (concat (xs :: ls))
lemma_take_head {ls = []} = Refl
lemma_take_head {ls = l :: ls} = ?h2
使用我的concat版本,这就像返回Refl一样容易。但是对于折叠的库版本,当Vect最不利时,我们得到以下上下文:
a : Type
l : List a
x : a
xs : List a
len : Nat
ls : Vect len (List a)
--------------------------------------
h2 : foldrImpl (\meth, meth => meth ++ meth) [] (\x1 => x :: xs ++ l ++ x1) ls = x :: foldrImpl (\meth, meth => meth ++ meth) [] (\x1 => xs ++ l ++ x1) ls
一旦证明到了这样的程度,有没有办法继续证明?还是唯一一种不使用折叠方式重新实现功能的解决方案?