Proof Idris中决策函数的构造证明

Proof Idris中决策函数的构造证明,proof,idris,theorem-proving,Proof,Idris,Theorem Proving,我试图为表示模块空间中两个连续元素的类型创建一个决策函数 (此代码是根据我前面的一个问题推导出来的。) 我已经尽了最大的努力,但我的知识还不够渊博,无法独自构造必要的证明,尤其是矛盾的证明。你能告诉我如何填写上述代码中的一个或多个选项吗 另外,如果你使用任何方便的工具,比如荒谬的,不可能的,或者,你能解释一下它们是如何工作的以及它们在证明中扮演的角色吗?而前面的sn中的prf构造函数需要LTE证明(LT a b只是LTE(a)b的同义词),您的第一个cmp只是拆分sa。相反,您应该直接获得LTE

我试图为表示模块空间中两个连续元素的类型创建一个决策函数

(此代码是根据我前面的一个问题推导出来的。)

我已经尽了最大的努力,但我的知识还不够渊博,无法独自构造必要的证明,尤其是矛盾的证明。你能告诉我如何填写上述代码中的一个或多个选项吗


另外,如果你使用任何方便的工具,比如
荒谬的
不可能的
,或者,你能解释一下它们是如何工作的以及它们在证明中扮演的角色吗?

前面的sn
中的
prf
构造函数需要
LTE
证明(
LT a b
只是
LTE(a)b
的同义词),您的第一个
cmp
只是拆分
sa
。相反,您应该直接获得
LTE
证明:

doesPreceedN m a b with (S (S a) `isLTE` m)
如果您不需要重用所有变量,那么省略
with
案例中的重复会让事情变得更美好。因此,要使用
LTE
重复您的版本,我们有:

  | (Yes lte) = case (decEq b (S a)) of
      Yes Refl => PreceedsS
      No notlte => No ?contra_notlte
  | (No notlte) with (decEq (S a) m)
    | Yes eq = case b of
      Z => Yes PreceedsZ
      (S b) => No ?contra_notZ
    | No noteq = No ?contra_noteq
在所有这些情况下,您需要a来证明一些
a->Void
,因此您可以假设,您拥有
a
。您可以创建一个引理(您的编辑器可能有用于该引理的绑定),或者使用带有大小写拆分的lambda。对于像这里这样的短函数,我倾向于后者。对于<代码>?对立面<代码>:

No (\contra => case contra of prec => ?contra_notZ)
如果您在
prec
上拆分,您将有:

No (\contra => case contra of PreceedsS => ?contra_notZ)
检查孔时,您将看到:

notlte : LTE (S (S b)) m -> Void
prf : LTE (S (S b)) m
prf
precedSS
的隐式参数,因此要将其纳入范围,可以对其进行匹配:

No (\contra => case contra of (PreceedsS {prf}) => notlte prf)
?相反的注释q
可以类似地解决

<代码>的lambda?相反

No notlte => No (\contra => case contra of
  PreceedsS => ?contra_notlte_1
  PreceedsZ => ?contra_notlte_2)
检查类型会得到:

:t ?contra_notlte_1
notlte : (S a = S a) -> Void
:t ?contra_notlte_2
lte : LTE (S (S a)) m
prf : S a = m
?contra\u notlte\u 2
是最棘手的,因为您不能只应用
notlte
。但是您可以看到,在
lte之后:lte(sm)m
应该为false,因此我们为它创建了一个函数:

notLTE : Not (LTE (S n) n)
notLTE LTEZero impossible
notLTE (LTESucc lte) = notLTE lte
现在我们有:

PreceedsZ {prf} => notLTE ?contra_notlte_2
?contra_notlte_2 : LTE (S n) n
我试图用
(在lte中重写prf)
来替换这个漏洞,但是没有成功,因为这个策略没有找到正确的属性来重写。但我们可以明确地说:

PreceedsZ {prf} => notLTE (replace prf lte)

> Type mismatch between
        LTE (S (S a)) m
and
        P (S a)
因此,我们通过设置
{p=(\x=>LTE(sx)m)}
来显式地设置
p

结果是:

doesPreceedN : (m : Nat) -> (a : Nat) -> (b : Nat) -> Dec (PreceedsN m a b)
doesPreceedN m a b with (S (S a) `isLTE` m)
  | (Yes lte) = case (decEq b (S a)) of
    Yes Refl => Yes PreceedsS
    No notlte => No (\contra => case contra of
      PreceedsS => notlte Refl
      PreceedsZ {prf} => notLTE  (replace prf {P=(\x => LTE (S x) m)} lte))
  | (No notlte) with (decEq (S a) m)
    | Yes eq = case b of
      Z => Yes PreceedsZ
      (S b) => No (\contra => case contra of (PreceedsS {prf}) => notlte prf)
    | No noteq = No (\contra => case contra of 
        PreceedsS {prf} => notlte prf
        PreceedsZ {prf} => noteq prf)

replace:(x=y)->px->py
只重写类型的一部分。 例如,使用
(n+m=m+n)
我们可以将
Vect(n+m)a
n+m
部分替换为
Vect(m+n)a
。这里
P=\to\u replace=>Vect to\u replace a
,因此
P
只是一个函数
Type->Type

doespreceden
中,我们需要明确说明
p
。大多数情况下,
rewrite…in…
(一种策略)可以自动找到此
P
,并应用
replace
<另一方面,code>replace
只是一个简单的函数
:printdef replace

replace : (x = y) -> P x -> P y
replace Refl prf = prf

我仍然无法准确理解
重写
的工作原理。你能展示一下没有这种策略代码会是什么样子吗;我的意思是
replace
replace
不是一种策略(
rewrite
是),而是一个简短的功能。没有更简单的方法来重写它而不替换
,但是我扩展了答案,对它们进行了解释;希望它能有所帮助!
replace : (x = y) -> P x -> P y
replace Refl prf = prf