通过列出所有案例来定义函数(例如`add`)是否有任何缺点?

时间:2018-03-22 04:23:27

标签: agda

添加通常定义为:

add : ℕ -> ℕ -> ℕ
add zero    m = m
add (suc n) m = suc (add n m)

这个定义很简短,但是使add-comm这样的事情证明相当复杂,需要两个归纳函数并调用substcongsym。相反,如果我们将add定义为:

add : ℕ -> ℕ -> ℕ
add zero    zero     = zero
add (suc n) zero     = suc n
add zero    (suc m)  = suc m
add (suc n) (suc m)  = suc (suc (add n m))

然后,交换性证明变得几乎无足轻重:

add-comm : forall a b -> add a b ≡ add b a
add-comm zero    zero    = refl
add-comm zero    (suc b) = refl
add-comm (suc a) zero    = refl
add-comm (suc a) (suc b) = cong suc (cong suc (add-comm a b))

通过列出所有案例而不是经济来定义像add这样的函数是否有任何消极方面?

1 个答案:

答案 0 :(得分:3)

你赢得了一些定义的平等,但你失去了其他人。在这种情况下,对于任何add (suc a) b,您都会失去suc (add a b) b。简而言之,如果您在此处有更多案例,则在其他地方需要更多案例和/或证据,例如Vec追加:

open import Data.Vec

add-zero : ∀ n → add zero n ≡ n
add-zero zero    = refl
add-zero (suc n) = refl

suc-add : ∀ n m → suc (add n m) ≡ add (suc n) m
suc-add zero zero = refl
suc-add zero (suc m) = cong suc (cong suc (sym (add-zero m)))
suc-add (suc n) zero = refl
suc-add (suc n) (suc m) rewrite suc-add n m = refl

append : ∀ {n m}{A : Set} → Vec A n → Vec A m → Vec A (add n m)
append []       ys = subst (Vec _) (sym (add-zero _)) ys
append (x ∷ xs) ys = subst (Vec _) (suc-add _ _) (x ∷ append xs ys)

(原始add-comm不需要两个定义):

add : ℕ -> ℕ -> ℕ
add zero    m = m
add (suc n) m = suc (add n m)

add-comm : ∀ n m → add n m ≡ add m n
add-comm zero    zero    = refl
add-comm zero    (suc m) = cong suc (add-comm zero m)
add-comm (suc n) zero    = cong suc (add-comm n zero)
add-comm (suc n) (suc m)
  rewrite add-comm n (suc m)
        | sym (add-comm (suc n) m)
        | add-comm n m = refl