重写在伊德里斯的工作究竟如何?

时间:2017-03-25 07:48:53

标签: dependent-type idris

我在伊德里斯写了以下命题:

total
plusOneCommutes : (n : Nat) -> (m : Nat) -> (n + S m = S n + m)
plusOneCommutes Z     k     = Refl
plusOneCommutes (S k) j     = 
 let inductiveHypothesis = plusOneCommutes k j in
   rewrite inductiveHypothesis in Refl

使用来自Prelude.Nat源代码的灵感,我理解为什么使用递归调用(在第二种情况下)作为归纳假设来证明这种情况是有意义的。但是,仔细阅读有关重写的详细信息,我并不真正理解其中发生的事情及其原因。

如果我写:

plusOneCommutes (S k) j     = ?hole

我从编译器中得到以下内容:

- + HolyGrail.hole [P]
 `--               k : Nat
                   j : Nat
     ------------------------------------------------------
      HolyGrail.hole : S (plus k (S j)) = S (S (plus k j))

这看起来并不合适。根据{{​​1}}的签名,此洞应具有plusOneCommutes类型。

如果我写的话,更进一步引入归纳假设:

(plus (S k) (S j)) = (plus (S (S k)) j)

然后plusOneCommutes (S k) j = let inductiveHypothesis = plusOneCommutes k j in ?hole 的类型变为:

hole

然后使用 - + HolyGrail.hole [P] `-- k : Nat j : Nat inductiveHypothesis : k + S j = S k + j ------------------------------------------------------------------------- HolyGrail.hole : S (plus k (S j)) = S (S (plus k j))

给出的重写规则
inductiveHypothesis

导致 - + HolyGrail.hole [P] `-- k : Nat j : Nat inductiveHypothesis : k + S j = S k + j _rewrite_rule : k + S j = S k + j ------------------------------------------------------------------------- HolyGrail.hole : (\replaced => S replaced = S (S (plus k j))) (S k + j) 这是预期的类型,而Idris可以使用S (plus (S k) j) = S (S (plus k j))自动替换?hole

令我感到困惑的是,我从签名推断出的内容与编译器从洞中推断的内容之间的类型出乎意料的差异。如果我自愿引入错误:

我收到以下消息:

Refl

- + Errors (1) `-- HolyGrail.idr line 121 col 16: When checking right hand side of plusOneCommutes with expected type S k + S j = S (S k) + j Type mismatch between S (S (plus k j)) = S (S (plus k j)) (Type of Refl) and S (plus k (S j)) = S (S (plus k j)) (Expected type) Specifically: Type mismatch between S (plus k j) and plus k (S j) 部分与上述步骤一致,但不是Type mismatch...部分,它给出了我期望的类型。

1 个答案:

答案 0 :(得分:4)

以下编译器实际上是有道理的:

- + HolyGrail.hole [P]
 `--               k : Nat
                   j : Nat
     ------------------------------------------------------
      HolyGrail.hole : S (plus k (S j)) = S (S (plus k j))

=类型的左侧,您有n + S m。在n上进行模式匹配后,您有(S k),并且S k + S j类型应为plus (S k) (S j)。在this question中,我解释了一个重要的观点:从编写plus函数的事实以及编译器可以在类型中执行模式匹配的事实,您只看到S (plus k (S j))正在应用{ {1}}至plus(S k)。与(S j)类似的情况。

现在到S n + m。在 Agda 编程语言中,rewrite只是rewrite上模式匹配的语法糖。有时你可以用 Idris 中的模式匹配替换Refl,但在这种情况下不能。

我们可以尝试做类似的事情。考虑下一个:

rewrite

编译器说下一个非常合理的事情:

total
plusOneCommutes : (n : Nat) -> (m : Nat) -> (n + S m = S n + m)
plusOneCommutes Z     k     = Refl
plusOneCommutes (S k) j     = case plusOneCommutes k j of
    prf => ?hole

- + HolyGrail.hole [P] `-- k : Nat j : Nat prf : k + S j = S k + j ------------------------------------------------------ HolyGrail.hole : S (plus k (S j)) = S (S (plus k j)) 证明prf是有道理的。使用k + S j = S k + j后:

rewrite

我们得到了:

plusOneCommutes (S k) j     = case plusOneCommutes k j of
    prf => rewrite prf in ?hole
Idris 中的

- + HolyGrail.hole [P] `-- k : Nat j : Nat prf : k + S j = S k + j _rewrite_rule : k + S j = S k + j ------------------------------------------------------------------------- HolyGrail.hole : (\replaced => S replaced = S (S (plus k j))) (S k + j) 的行为方式如下:

  1. 使用rewrite个对象和Refl : left = right
  2. expr : t中搜索left
  3. 将所有t替换为left中的right
  4. 在我们的案例中:

    1. tt
    2. S (plus k (S j)) = S (S (plus k j))
      • Refl : plus k (S j) = plus (S k) jleft
      • plus k (S j)right
    3. Idris将plus (S k) j(左)替换为plus k (S j)中的plus (S k) j(右),我们得到t。 Idris可以执行模式匹配。而S (plus (S k) j) = S (S (plus k j))自然会成为S (plus (S k) j)