给定(x = y)&(xs = ys)的情况下如何证明((x :: xs)=(y :: ys))

时间:2018-07-29 16:09:49

标签: idris

我正在学习Idris,还有一个菜鸟问题。

我正在做关于Idris的类型驱动开发的书的第8.3章的练习2。关键是要为自己的DecEq实现Vector。这就是我走的距离:

data Vect : Nat -> Type -> Type where
  Nil : Vect 0 elem
  (::) : elem -> Vect n elem -> Vect (S n) elem

headUnequal : {xs : Vect n a} -> {ys : Vect n a} -> (contra : (x = y) -> Void) -> ((x :: xs) = (y :: ys)) -> Void
headUnequal contra Refl = contra Refl

tailsUnequal : {xs : Vect n a} -> {ys : Vect n a} -> (contra : (xs = ys) -> Void) -> ((x :: xs) = (y :: ys)) -> Void
tailsUnequal contra Refl = contra Refl

headAndTailEq : {xs : Vect n a} -> {ys : Vect n a} -> (xEqY : x = y) -> (xsEqYs : xs = ys) -> ((x :: xs) = (y :: ys))
headAndTailEq xEqY xsEqYs = ?hole

implementation DecEq a => DecEq (Vect n a) where
  decEq [] [] = Yes Refl
  decEq (x :: xs) (y :: ys) =
    case decEq x y of
      No xNeqY => No $ headUnequal xNeqY
      Yes xEqY => case decEq xs ys of
        No xsNeqYs => No $ tailsUnequal xsNeqYs
        Yes xsEqYs => Yes $ headAndTailEq xEqY xsEqYs

如何填充?hole

我已经看到了https://github.com/edwinb/TypeDD-Samples/blob/master/Chapter8/Exercises/ex_8_3.idr上的解决方案。有了这些知识,我就可以使我的解决方案起作用:

implementation DecEq a => DecEq (Vect n a) where
  decEq [] [] = Yes Refl
  decEq (x :: xs) (y :: ys) =
    case decEq x y of
      No xNeqY => No $ headUnequal xNeqY
      Yes Refl => case decEq xs ys of
        No xsNeqYs => No $ tailsUnequal xsNeqYs
        Yes Refl => Yes Refl

但是说实话,这为什么起作用?为什么最后的Yes Refl仅在我不打样的情况下才能起作用?

谢谢!

1 个答案:

答案 0 :(得分:2)

重要的区别是case块中的值匹配,而不是证明的命名。如果您使用

检查第一个case
  decEq (x :: xs) (y :: ys) =
    case decEq x y of
      No xNeqY => No $ headUnequal xNeqY
      Yes Refl => ?hole

您将看到?hole仅需要Dec (x :: xs = x :: ys)。另一方面,在您的版本中,?holeDec (x :: xs = y :: ys)

  decEq (x :: xs) (y :: ys) =
    case decEq x y of
      No xNeqY => No $ headUnequal xNeqY
      Yes xEqY => ?hole

在这里xEqY : x = y。 Idris对=并没有特殊的了解,因此,这仅意味着存在一个值为xEqY的值x = y(并且没有进一步检查xEqY的内容)可能)。如果您在Refl上匹配,则Idris可以统一xy,因为Reflx = x的构造函数-值是相同的。因此,您可以通过模式匹配获得更多信息;而不是一个不透明的变量名,您将得到一个具体的值。凭经验:始终进行模式匹配,直到您在右侧有足够的信息为止。

有了这个,您的证明也可以轻松实现:

headAndTailEq : {xs : Vect n a} -> {ys : Vect n a} -> (xEqY : x = y) -> (xsEqYs : xs = ys) -> ((x :: xs) = (y :: ys))
headAndTailEq Refl Refl = Refl