使用Lean,计算机证明检查系统。
第一个证明成功,第二个证明不成功。
variables n m : nat
theorem works (h1 : n = m) (h2 : 0 < n) : (0 < m) :=
eq.subst h1 h2
theorem nowrk (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
eq.subst h3 h4
错误发生在eq.subst
中,如下所示:
"eliminator" elaborator type mismatch, term
h4
has type
0 < n
but is expected to have type
n < n
[然后是一些额外的信息]
我不理解错误消息。我在假设中尝试了各种明显的排列,例如0 = n或n&gt; 0,但我无法让它工作,或者产生一个我能理解的错误信息。
任何人都可以澄清吗?我阅读了关于congr_arg
等关于定理的定理的部分,但这些其他命令并没有帮助我。
答案 0 :(得分:3)
eq.subst
依赖于更高阶的统一来计算替换的动机,这本身就是一种启发式和一种挑剔的过程。在你的第二个案例中,精益的启发式失败了。 (您可以在错误消息中看到错误的动机。)还有其他方法可以更智能地执行此操作。
使用自动化:
theorem nowrk (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
by simp * at * -- this may not work on 3.2.0
theorem nowrk2 (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
by cc
使用重写:
theorem nowrk3 (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
by rw h3 at h4; assumption
使用eq.subst
并明确给出动机:
theorem nowrk4 (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
@eq.subst _ (λ h, 0 < h) _ _ h3 h4
theorem nowrk4' (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
@eq.subst _ ((<) 0) _ _ h3 h4 -- more concise notation for the above
使用计算模式:
theorem nowrk5 (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
calc 0 < n : h4
... = 0 : h3
使用模式匹配:
theorem nowork6 : Π n, n = 0 → 0 < n → 0 < 0
| ._ rfl prf := prf
答案 1 :(得分:2)
首先,为您的函数提供有意义的名称是一种很好的编程习惯。
第一个引理可以被称为subst_ineq_right
或subst_ineq
,如果从上下文中可以清楚地看到你总是在右边替换。
现在,在你的第一个引理的情况下,阐明者将合成哪个术语是明确的。如果h1
类型为n = m
,h2
类型为0 < n
,则详细信息器会some complicated recursor magic代替n
代替m
0 < n
并根据需要生成0 < m
类型的术语:
lemma subst_ineq (h1 : n = m) (h2 : 0 < n) : (0 < m) :=
eq.subst h1 h2
不幸的是,你的第二个引理失败了,比如subst_zero_ineq
lemma subst_zero_ineq (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
eq.subst h3 h4
这是因为现在对于阐述者将合成的术语存在歧义。它可以替换n
中的0
,或0
中的n
替换0 < n
。由于不可思议的原因,阐述者选择做后者,产生n < n
类型的术语。结果不是0 < 0
类型的术语,并且证明不会键入check。
消除不明确性的一种方法是在subst_ineq
的证明中使用subst_zero_ineq
,例如:
lemma subst_zero_ineq (h3 : n = 0) (h4 : 0 < n) : (0 < 0) :=
subst_ineq n 0 h3 h4
typechecs正确。