首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何告诉Agda展开定义以证明等价性

如何告诉Agda展开定义以证明等价性
EN

Stack Overflow用户
提问于 2022-06-28 21:50:01
回答 1查看 86关注 0票数 3

我有这样的功能:

代码语言:javascript
复制
open import Data.Char
open import Data.Nat
open import Data.Bool
open import Relation.Binary.PropositionalEquality
open Relation.Binary.PropositionalEquality.≡-Reasoning

foo : Char → Char → ℕ
foo c1 c2 with c1 == c2
... | true = 123
... | false = 456

我想证明,当我用相同的参数(foo c c)调用它时,它总是产生123

代码语言:javascript
复制
foo-eq⇒123 : ∀ (c : Char) → foo c c ≡ 123
foo-eq⇒123 c =
  foo c c ≡⟨ {!!} ⟩
  123 ∎

我能够使用refl来证明一个简单的例子:

代码语言:javascript
复制
foo-example : foo 'a' 'a' ≡ 123
foo-example = refl

所以,我想我可以把refl放进洞里,因为Agda所需要做的就是减少foo c c。但是,用refl替换这个洞会产生以下错误:

代码语言:javascript
复制
.../Unfold.agda:15,14-18
(foo c c
 | Relation.Nullary.Decidable.Core.isYes
   (Relation.Nullary.Decidable.Core.map′ Data.Char.Properties.≈⇒≡
    Data.Char.Properties.≈-reflexive
    (Relation.Nullary.Decidable.Core.map′
     (Data.Nat.Properties.≡ᵇ⇒≡ (toℕ c) (toℕ c))
     (Data.Nat.Properties.≡⇒≡ᵇ (toℕ c) (toℕ c)) (T? (toℕ c ≡ᵇ toℕ c)))))
!= 123 of type ℕ
when checking that the expression refl has type foo c c ≡ 123

我怀疑问题是,Agda并不会自动理解c == ctrue for all c

代码语言:javascript
复制
c==c : ∀ (c : Char) → (c == c) ≡ true
c==c c = refl
代码语言:javascript
复制
.../Unfold.agda:23,10-14
Relation.Nullary.Decidable.Core.isYes
(Relation.Nullary.Decidable.Core.map′ Data.Char.Properties.≈⇒≡
 Data.Char.Properties.≈-reflexive
 (Relation.Nullary.Decidable.Core.map′
  (Data.Nat.Properties.≡ᵇ⇒≡ (toℕ c) (toℕ c))
  (Data.Nat.Properties.≡⇒≡ᵇ (toℕ c) (toℕ c)) (T? (toℕ c ≡ᵇ toℕ c))))
!= true of type Bool
when checking that the expression refl has type (c == c) ≡ true

那么,证明我的foo-eq⇒123定理的正确方法是什么呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-29 11:58:10

Agda的内置Char类型有点奇怪。让我们将其与一个非怪异的内置类型进行对比。的等式测试如下所示。

代码语言:javascript
复制
_≡ᵇ_ : Nat → Nat → Bool
zero  ≡ᵇ zero  = true
suc n ≡ᵇ suc m = n ≡ᵇ m
_     ≡ᵇ _     = false

请注意,n ≡ᵇ n也不会减少到true。毕竟,Agda不知道nzero还是suc,也就是说,这两个条款中的哪一个申请减值。因此,这与您的Char示例有相同的问题。但对于来说,有一条简单的出路。

让我们再次查看您的示例,并添加-based版本的foobar

代码语言:javascript
复制
open import Data.Char using (Char ; _==_ ; _≟_)
open import Data.Nat using (ℕ ; zero ; suc ; _≡ᵇ_)
open import Data.Bool using (true ; false)
open import Relation.Binary.PropositionalEquality using (_≡_ ; refl)
open import Relation.Nullary using (yes ; no)
open import Relation.Nullary.Negation using (contradiction)

foo : Char → Char → ℕ
foo c1 c2 with c1 == c2
... | true  = 123
... | false = 456

bar : ℕ → ℕ → ℕ
bar n1 n2 with n1 ≡ᵇ n2
... | true  = 123
... | false = 456

那么,对于来说,最简单的出路是什么?我们用模式匹配/在n上做一个案例分割,以减少n ≡ᵇ n,以完成我们的证明。也就是说,要么用大小写zero,要么到下一个递归步骤suc n

代码语言:javascript
复制
bar-eq⇒123 : ∀ n → bar n n ≡ 123
bar-eq⇒123 zero    = refl
bar-eq⇒123 (suc n) = bar-eq⇒123 n

只有两个构造函数,我们知道≡ᵇ是什么样子的,所以模式匹配是直接的。

对于Char来说,事情要复杂得多。长话短说,Char的等式测试是用一个toℕ函数定义的,而Agda并没有给我们一个定义。而且,Char数据类型是假定的,不附带任何构造函数。因此,像bar-eq⇒123这样的证据对于Char来说不是一种选择。我们没有子句,也没有构造函数。(我不认为'a'Char的构造函数。类似于1234如何不是的构造函数。)

那么,我们能做什么呢?请注意,您引用的错误消息中的c == c简化为涉及isYes的相当复杂的内容。如果我们只将c == c减少一点点(而不是尽可能地减少),我们就会得到isYes (c ≟ c) (而不是从错误消息中得到复杂的东西)。

_≟_Char的可判定等式(即“等于还是不等于?”)布尔值和证明)。isYes去掉了证明并给出了布尔值。

那么,我对证据的想法将不是在c上进行案例分割(就像我们对那样),而是在c ≟ c上。这将产生两种情况,并将isYes分别减少为truefalsetrue的情况是显而易见的。false一案与可判定等式的证明相矛盾。

代码语言:javascript
复制
foo-eq⇒123 : ∀ c → foo c c ≡ 123
foo-eq⇒123 c with c ≟ c
... | yes p = refl
... | no ¬p = contradiction refl ¬p

请注意,这个证明不容易转换为,因为_≡ᵇ_不是基于可判定的等式和isYes。而是一种原始的。

也许更好的方法是坚持可判定的平等,对于Char,而不是使用_==__≡ᵇ_。然后,foo将如下所示。

代码语言:javascript
复制
baz : Char → Char → ℕ
baz c1 c2 with c1 ≟ c2
... | yes p = 123
... | no ¬p = 456

foo-eq⇒123证明对它也没有影响。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72793516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档