如何在Idris中为证据重写类型签名中的术语?

时间:2017-09-11 07:12:47

标签: idris proof-of-correctness

基本上,我想证明递归算术中n - mm - n等于零。为了实现这一点,我一直试图使用rewrite ... in ...模式而没有成功。

以下是基本代码:

data Natural = C | S Natural

resta : Natural -> Natural -> Natural
resta a     C     = a
resta C     b     = C
resta (S a) (S b) = resta a b

data AlgunoEsCero : (n, m : Natural) -> Type where
  IzquierdoEsCero : AlgunoEsCero C m
  DerechoEsCero :   AlgunoEsCero n C

alguna_resta_es_cero : (n, m: Natural) -> AlgunoEsCero (resta n m) (resta m n)
alguna_resta_es_cero C     m     = ?hoyo1
alguna_resta_es_cero n     C     = ?hoyo2
alguna_resta_es_cero (S n) (S m) = ?hoyo3

然而,在检查前两个孔时

- + Main.hoyo1 [P]
 `--           m : Natural
     -----------------------------------------
      Main.hoyo1 : AlgunoEsCero (resta C m) m

- + Main.hoyo2 [P]
 `--           n : Natural
     -----------------------------------------
      Main.hoyo2 : AlgunoEsCero n (resta C n)

我能够前进的唯一方法是data AlgunoEsCero中的引理;从我所读到的前进方向是使用另一个定理重写类型,如

cero_menos_algo_es_cero : (m: Natural) -> resta C m = C
cero_menos_algo_es_cero C     = Refl
cero_menos_algo_es_cero (S m) = Refl

那么很容易指出两个减号中的哪一个将为零并使用rewrite cero_menos_algo_es_cero in IzquierdoEsCero之类的东西构建数据类型。然而,吐出来了:

When checking right hand side of alguna_resta_es_cero with expected type
             AlgunoEsCero (resta C m) (resta m C)

     _ does not have an equality type ((m1 : Natural) -> resta C m1 = C)

任何资源指针都将受到赞赏。 (Haven能够在类型驱动开发和文档中找到好点;也许我误解了rewrite /一般的证据)

1 个答案:

答案 0 :(得分:1)

你需要再次模式匹配才能完成证明:

alguna_resta_es_cero : (n, m: Natural) -> AlgunoEsCero (resta n m) (resta m n)
alguna_resta_es_cero C C = IzquierdoEsCero
alguna_resta_es_cero C (S x) = IzquierdoEsCero
alguna_resta_es_cero (S x) C = DerechoEsCero
alguna_resta_es_cero (S x) (S y) = alguna_resta_es_cero x y

此外,如果您将减法功能定义为

resta : Natural -> Natural -> Natural
resta C     b     = C
resta a     C     = a
resta (S a) (S b) = resta a b

(注意我在第一个参数上进行模式匹配,而不是在第二个参数上使用启动模式匹配的版本),然后 alguna_resta_es_cero的证明将更密切地模仿函数的结构:

alguna_resta_es_cero : (n, m: Natural) -> AlgunoEsCero (resta n m) (resta m n)
alguna_resta_es_cero C m = IzquierdoEsCero
alguna_resta_es_cero (S x) C = DerechoEsCero
alguna_resta_es_cero (S x) (S y) = alguna_resta_es_cero x y