你的增量函数不正确。考虑到你对二进制数的定义:
data Bin : Set where
â¨â© : Bin
_O : Bin â Bin
_I : Bin â Bin
inc : Bin â Bin
inc â¨â© = â¨â© I
inc (x O) = x I
inc (x I) = (inc x) O
当右边的数字是0时,你只要用1来代替它,但是你不能忘记保留数字的左边部分。
新算法的快速验证
验证这样一个函数的一个好方法是评估它应该提供哪些属性。增量函数的结果必须等于1加上其输入值。Agda提供了自然数,所以让我们将二进制数转换成自然数来检查这样的属性。首先,一些进口产品:
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
然后是一个将二进制数转换成自然数的函数:
_â : Bin â â
â¨â© â = 0
(x O) â = x â + x â
(x I) â = suc (x â + x â)
最后,我们的验证属性:
prop : â {b} â (inc b) â â¡ suc (b â)
prop {â¨â©} = refl
prop {b O} = refl
prop {b I} rewrite prop {b} | +-suc (b â) (b â) = refl
这个验证当然是不完整的(本质上),但至少它让你对你的算法有信心。在编写算法时,您应该始终尝试并证明这样的假设,这是Agda的全部观点(不是全部观点,但至少是部分观点)。
有关验证的详细信息
为了进一步说明我的观点,我决定尝试通过实现从自然数到二进制数的倒数转换来验证二进制数的表示:
_â : â â Bin
zero â = â¨â©
suc n â = inc (n â)
我们可以直接证明这两个变换在上下时是相互的:
ââ : â {n} â (n â) â â¡ n
ââ {zero} = refl
ââ {suc n} rewrite prop {n â} | ââ {n} = refl
然后我试着用另一种方法:
ââ : â {b} â (b â) â â¡ b
ââ {â¨â©} = refl
ââ {b O} rewrite propâ {b â} rewrite ââ {b} = refl
ââ {b I} rewrite propâ {b â} rewrite ââ {b} = refl
这边需要
propâ
propâ : â {n} â (n + n) â â¡ (n â) O
这个属性应该是真的(在这个意义上,我们认为二进制数应该满足它),但是它不能在你的形式主义中被证明,因为你可以用无数种方式来表示零,而且所有这些方式都不是介词相等的(例如
道具
n
等于
0
需要证明
â¨â© â¡ (â¨â© O)
无法证明)。
作为旁注,我并不是说应该总是有一种方法来表示抽象数据类型的特定元素,但它确实有帮助,特别是在处理命题等式时,这是经常需要的。
另一方面,我很抱歉,如果我有点失控,但我发现这些话题非常启发有关使用证明助理和正式验证。
请随时要求进一步解释。
module BinaryNumber where
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
data Bin : Set where
â¨â© : Bin
_O : Bin â Bin
_I : Bin â Bin
inc : Bin â Bin
inc â¨â© = â¨â© I
inc (x O) = x I
inc (x I) = (inc x) O
_â : Bin â â
â¨â© â = 0
(x O) â = x â + x â
(x I) â = suc (x â + x â)
prop : â {b} â (inc b) â â¡ suc (b â)
prop {â¨â©} = refl
prop {b O} = refl
prop {b I} rewrite prop {b} | +-suc (b â) (b â) = refl
_â : â â Bin
zero â = â¨â©
suc n â = inc (n â)
ââ : â {n} â (n â) â â¡ n
ââ {zero} = refl
ââ {suc n} rewrite prop {n â} | ââ {n} = refl
propâ : â {n} â (n + n) â â¡ (n â) O
propâ {zero} = {!!}
propâ {suc n} = {!!}
ââ : â {b} â (b â) â â¡ b
ââ {â¨â©} = refl
ââ {b O} rewrite propâ {b â} rewrite ââ {b} = refl
ââ {b I} rewrite propâ {b â} rewrite ââ {b} = refl
标准图书馆
最后一句话,二进制数存在于文件的标准库中
Data.Nat.Binary.Base
Data.Nat.Binary.Properties
如果你想看看他们是如何实现的。