+comm : ∀ (x y : N) → x + y ≡ y + x +comm zero y = { }0 --{ }0 is a hole +comm (suc x) y = { }1 --------------------------------------------------------- ?0 : zero + y ≡ y + zero ?1 : suc x + y ≡ y + suc x
我们接下来就可以基于这些提示来完成证明了。
观察 hole0。
1 2 3
Goal: y ≡ y+0 -------------------------------------------------- y: N
左边按照加法定义展开之后,我们得到的是 y ≡ y + zero,这时候我们就可以使用 +0 来完成证明了。
1 2 3
+comm : ∀ (x y : N) → x + y ≡ y + x +comm zero y rewrite +0 y = refl +comm (suc x) y = { }0
观察 hole1。
1 2 3 4
Goal: suc (x + y) ≡ y + suc x --------------------------------------------------------- y : N x : N
尝试用归纳假设重写一下,这样可以使 x 和 y 的位置在左右两边对称。
1 2 3
+comm : ∀ (x y : N) → x + y ≡ y + x +comm zero y rewrite +0 y = refl +comm (suc x) y rewrite +comm x y = { }0
再次观察 hole1。
1 2 3 4
Goal: suc (y + x) ≡ y + suc x --------------------------------------------------------- y : N x : N
此外,Agda 不像 Haskell 那样无需顾及函数在代码中定义的顺序,所以我们在写代码时必须把辅助引理写在主要的证明之前,否则 Agda 会提示我们找不到辅助引理(not in scope)。
证明乘法的分配律
1 2 3
*distrib : ∀ (x y z : ℕ) → (x + y) * z ≡ (x * z) + (y * z) *distrib zero y z = refl *distrib (suc x) y z rewrite *distrib x y z | +assoc z (x * z) (y * z) = refl
import Relation.Binary.PropositionalEquality as Eq open Eq using (_≡_; refl; sym) open import Data.Bool
data ℕ : Set where zero : ℕ suc : ℕ → ℕ infixl 6 _+_ _+_ : ℕ → ℕ → ℕ zero + n = n suc m + n = suc (m + n) infixl 7 _*_ _*_ : ℕ → ℕ → ℕ zero * n = zero suc m * n = n + (m * n)
pred : ℕ → ℕ pred zero = zero pred (suc n) = n
0+ : ∀(x : ℕ) → zero + x ≡ x 0+ x = refl
+0 : ∀(x : ℕ) → x + zero ≡ x +0 zero = refl +0 (suc x) rewrite +0 x = refl
+assoc : ∀ (x y z : ℕ) → x + (y + z) ≡ (x + y) + z +assoc zero y z = refl +assoc (suc x) y z rewrite +assoc x y z = refl
+suc : ∀ (x y : ℕ) → x + suc y ≡ suc (x + y) +suc zero y = refl +suc (suc x) y rewrite +suc x y = refl
+comm : ∀ (x y : ℕ) → x + y ≡ y + x +comm zero y rewrite +0 y = refl +comm (suc x) y rewrite +comm x y | +suc y x = refl
*distrib : ∀ (x y z : ℕ) → (x + y) * z ≡ (x * z) + (y * z) *distrib zero y z = refl *distrib (suc x) y z rewrite *distrib x y z | +assoc z (x * z) (y * z) = refl
_<ℕ_ : ℕ → ℕ → Bool zero <ℕ zero = false zero <ℕ suc y = true suc x <ℕ zero = false suc x <ℕ suc y = x <ℕ y
_=ℕ_ : ℕ → ℕ → Bool zero =ℕ zero = true zero =ℕ suc y = false suc x =ℕ zero = false suc x =ℕ suc y = x =ℕ y
_≤ℕ_ : ℕ → ℕ → Bool zero ≤ℕ zero = true zero ≤ℕ suc y = true suc x ≤ℕ zero = false suc x ≤ℕ suc y = x ≤ℕ y
=ℕ-from-≡ : ∀ {x y : ℕ} → x ≡ y → x =ℕ y ≡ true =ℕ-from-≡ {x} refl = =ℕ-refl x
isEven : ℕ → Bool isOdd : ℕ → Bool isEven zero = true isEven (suc x) = isOdd x isOdd zero = false isOdd (suc x) = isEven x
~_ : Bool → Bool ~ true = false ~ false = true
even~odd : ∀ (x : ℕ) → isEven x ≡ ~ isOdd x odd~even : ∀ (x : ℕ) → isOdd x ≡ ~ isEven x even~odd zero = refl even~odd (suc x) = odd~even x odd~even zero = refl odd~even (suc x) = even~odd x
+assoc2 : ∀ (x y z : ℕ) → (x + y) + z ≡ x + (y + z) +assoc2 zero y z = refl +assoc2 (suc x) y z rewrite +assoc2 x y z = refl
+-swap : ∀ (x y z : ℕ) → x + (y + z) ≡ y + (x + z) +-swap x y z rewrite sym(+assoc2 y x z) | sym(+assoc2 x y z) | +comm x y = refl
*0 : ∀ (x : ℕ) → x * zero ≡ zero *0 zero = refl *0 (suc x) rewrite *0 x = refl
*-suc : ∀ (x y : ℕ) → x * suc y ≡ x + x * y *-suc zero y = refl *-suc (suc x) y rewrite *-suc x y | +-swap y x (x * y) = refl
*-comm : (x y : ℕ) → x * y ≡ y * x *-comm zero y rewrite *0 y = refl *-comm (suc x) y rewrite *-suc y x | *-comm x y = refl
+-samex : ∀ (x y z : ℕ) → y ≡ z → x + y ≡ x + z +-samex zero y z p = p +-samex (suc x) y z p rewrite +-samex x y z p = refl
*-distri2 : (x y z : ℕ) → x * (y + z) ≡ x * y + x * z *-distri2 zero y z = refl *-distri2 (suc x) y z rewrite *-distri2 x y z | +assoc2 y z (x * y + x * z) | +assoc2 y (x * y) (z + x * z) = +-samex y (z + (x * y + x * z)) (x * y + (z + x * z)) (+-swap z (x * y) (x * z))
-- problem 1.2: associativity of _*_ *-assoc : (x y z : ℕ) → (x * y) * z ≡ x * (y * z) *-assoc zero y z = refl *-assoc (suc x) y z rewrite *-assoc x y z | sym(+assoc2 y z (x * y + x * z)) | *-comm (y + x * y) z | *-distri2 z y (x * y) | *-comm z y | *-comm z (x * y) | sym(*-assoc x y z) = refl
-- 反对称性 <-antisym : (x y : ℕ) → (x <ℕ y) ≡ true → (y <ℕ x) ≡ false <-antisym zero zero () <-antisym (suc x) zero () <-antisym zero (suc y) p = refl <-antisym (suc x) (suc y) p rewrite <-antisym x y p = refl
-- 三岐性 infix 20 _or_ _or_ : Bool → Bool → Bool true or _ = true false or b = b
<-trichotomy : (x y : ℕ) → (((x <ℕ y) or (x =ℕ y)) or (y <ℕ x)) ≡ true <-trichotomy zero zero = refl <-trichotomy (suc x) zero = refl <-trichotomy zero (suc y) = refl <-trichotomy (suc x) (suc y) rewrite <-trichotomy x y = refl