我在上一个问题Using the value of a computed function for a proof in agda中看到过检查功能的一个例子,但是我仍然无法绕过那个问题。
这是一个简单的例子:
给定函数crazy
,
crazy : ℕ -> ℕ
crazy 0 = 10
crazy 1 = 0
crazy 2 = 0
crazy 3 = 1
crazy 4 = 0
crazy xxx = xxx
我想创建一个safe
函数,使safe : {nn : ℕ} -> (id nn) ≢ 0 -> Fin (id nn)
。换句话说,它会返回一个数字mod疯狂,如果你给它一个疯狂的证据是0.(我知道这个例子有点做作,我可能最好在函数签名中使用suc
)
我的第一个解决方案是
safebad : {nn : ℕ} -> (crazy nn) ≢ 0 -> Fin (crazy nn)
safebad {1} hh with hh refl
... | ()
safebad {2} hh with hh refl
... | ()
safebad {4} hh with hh refl
... | ()
safebad {0} hh = # 0
safebad {3} hh = # 0
safebad {suc (suc (suc (suc (suc _))))} _ = # 0
但这很漫长而且很混乱。所以我试图在Using the value of a computed function for a proof in agda中模仿这个例子,但只能到目前为止
safegood : (nn : ℕ) -> (crazy nn) ≢ 0 -> Fin (crazy nn)
safegood nn nez with crazy nn | inspect crazy nn
... | 0 | [ proof ] = ⊥-elim ???
... | _ | _ = # 0
inspect使用Hidden来隐藏类型签名中的函数应用程序的记录,我想。然后可以使用揭示来检索。
我认为这是我理解的:
Reveal_is_
似乎保留了隐藏f
和x
的值;以及x
的结果应用于f
。 [_]
将证明这种平等。
⊥-elim
证明了矛盾,并引发了矛盾。
我将???
用于此工作的内容是什么?
答案 0 :(得分:3)
你正在使它变得不必要地复杂化。 inspect
仅在需要使用模式匹配前的值等于模式匹配后的值的证明时才有用。请注意,您在范围内有nez
,这使得这很简单。
我们真正想要做的是将假设crazy nn ≢ 0
减少到0 ≢ 0
,我们可以轻松地将其用于构建矛盾。我们如何将crazy nn
缩减为0
?您已经尝试过第一个选项 - 浏览所有可能的crazy
参数,然后查找确实将crazy nn
缩减为0
的参数。另一种选择是简单地抽象crazy nn
。
首先,我们使用with
之前的目标类型是Fin (crazy nn)
,nez
的类型是crazy nn ≢ 0
。现在,我们抽象crazy nn
:
safegood nn nez with crazy nn
... | w = ?
请注意,我们的目标现在是Fin w
,nez
的类型为w ≢ 0
,更容易使用!最后,我们在w
上模式匹配:
safegood nn nez with crazy nn
... | zero = ?
... | suc w = ?
第一个目标现在是Fin 0
,我们有一个0 ≢ 0
作为我们的假设之一。这显然是一个废话,将nez
与refl
结合起来给我们提供了⊥-elim
可以使用的矛盾:
safegood nn nez with crazy nn
... | zero = ⊥-elim (nez refl)
... | suc w = ?
看不到inspect
!事实上,在这里使用inspect
就像往返一样:您将类型中的crazy nn
缩减为0
,获得crazy nn ≡ 0
的证明,现在您需要“无法减少“0
返回crazy nn
,以便您可以使用nez proof
。
为了完整起见:您可以通过使用已弃用的crazy nn
来避免nez
上的模式匹配,以保持证明inspect
的类型完整:
open Deprecated-inspect
renaming (inspect to inspect′)
safegood₂ : (nn : ℕ) → crazy nn ≢ 0 → Fin (crazy nn)
safegood₂ nn nez with inspect′ (crazy nn)
... | zero with-≡ eq = ⊥-elim (nez eq)
... | suc _ with-≡ eq = ?
由于我们抽象inspect′ (crazy nn)
,所以没有crazy nn
子表达式被替换,nez
将保留其原始类型。
谈论疯狂的往返:您可以使用proof
来重建nez
的原始类型;再次,这更像是“可能有用的知识”,而不是“在这里使用”:
safegood : (nn : ℕ) → crazy nn ≢ 0 → Fin (crazy nn)
safegood nn nez with crazy nn | inspect crazy nn
... | 0 | [ proof ] = ⊥-elim (subst (λ x → x ≢ 0) (sym proof) nez proof)
... | _ | _ = ?