在Refl中使用重写

时间:2017-12-30 20:15:38

标签: idris

我正在使用Idris进行第8章类型驱动开发,我有一个关于重写如何与Refl交互的问题。

此代码显示为重写如何对表达式起作用的示例:

myReverse : Vect n elem -> Vect n elem
myReverse [] = []
myReverse {n = S k} (x :: xs)
    = let result = myReverse xs ++ [x] in
          rewrite plusCommutative 1 k in result

其中plusCommutative 1 k将查找1 + k的任何实例,并将其替换为k + 1

我的问题是这个解决方案将plusCommutative作为myPlusCommutes的一部分进行重写,答案是:

myPlusCommutes : (n : Nat) -> (m : Nat) -> n + m = m + n
myPlusCommutes Z m = rewrite plusZeroRightNeutral m in Refl
myPlusCommutes (S k) m = rewrite myPlusCommutes k m in
                         rewrite plusSuccRightSucc m k in Refl

我遇到这条线路有问题:

myPlusCommutes Z m = rewrite plusZeroRightNeutral m in Refl

因为我可以通过在该行中单独使用Refl来理解:

myPlusCommutes Z m = Refl

我收到此错误:

When checking right hand side of myPlusCommutes with expected type
        0 + m = m + 0

Type mismatch between
        plus m 0 = plus m 0 (Type of Refl)
and
        m = plus m 0 (Expected type)

Specifically:
        Type mismatch between
                plus m 0
        and
                m

首先,我没有意识到的一件事是,似乎Refl在=的右侧起作用并寻求从那个方向反射。

接下来,似乎重写Refl会导致从plus m 0 = plus m 0更改为m = plus m 0,从左侧重写但在第一次替换后停止,并且不会更换所有实例正如我所期望的那样plus m 0 m

最终,这是我的问题,为什么重写会以这种方式表现。重写相等类型是不同的,在这些情况下,重写仅替换=的左侧?

1 个答案:

答案 0 :(得分:2)

为了理解这里发生了什么,我们需要考虑Refl是多态的这一事实:

λΠ> :set showimplicits
λΠ> :t Refl
Refl : {A : Type} -> {x : A} -> (=) {A = A} {B = A} x x

这意味着Idris正试图使用​​来自上下文的信息将类型归因于术语Refl。例如。 Refl中的myPlusCommutes Z m = Refl类型为plus m 0 = plus m 0。 Idris本可以选择myPlusCommutes'输出类型的LHS,并尝试将类型m = m归因于Refl。您也可以像x一样指定Refl {x = m}表达式。

现在,rewrite适用于您的当前目标,即rewrite EqEq的LHS的所有出现替换为其< em>目标,而不是Refl的某些可能类型。

让我举一个使用一系列重写来说明我的意思的愚蠢的例子:

foo : (n : Nat) -> n = (n + Z) + Z
foo n =
  rewrite sym $ plusAssociative n Z Z in   -- 1
  rewrite plusZeroRightNeutral n in        -- 2 
  Refl                                     -- 3
  • 我们从目标n = (n + Z) + Z开始,然后是
  • 第1行使用关联法则将目标转换为n = n + (Z + Z),然后
  • 第2行将当前目标n = n + Z(定义上等于n = n + (Z + Z))转换为n = n
  • 第3行提供了当前目标的证明术语(如果我们想要更明确,我们可以用Refl {x = n}代替Refl)。