[英]Automatically and deterministicly testing a function for associativity, commutativity etc
[英]Agda Type-Checking and Commutativity / Associativity of +
由於Nat
的_+_
-Operation通常是在第一個參數中遞歸定義的,因此對於類型檢查器而言,知道i + 0 == i
顯然是非常重要的。 但是,當我在固定大小的向量上編寫函數時,我經常遇到這個問題。
一個例子:我如何定義Agda函數
swap : {A : Set}{m n : Nat} -> Vec A (n + m) -> Vec A (m + n)
它將前n
值放在向量的末尾?
因為Haskell中的簡單解決方案是
swap 0 xs = xs
swap n (x:xs) = swap (n-1) (xs ++ [x])
我在Agda中類似地嘗試過這樣的:
swap : {A : Set}{m n : Nat} -> Vec A (n + m) -> Vec A (m + n)
swap {_} {_} {zero} xs = xs
swap {_} {_} {suc i} (x :: xs) = swap {_} {_} {i} (xs ++ (x :: []))
但是類型檢查器失敗並顯示消息(與上面的swap
-Definition中的{zero}
-case相關):
.m != .m + zero of type Nat
when checking that the expression xs has type Vec .A (.m + zero)
所以,我的問題:如何教Agda, m == m + zero
? 以及如何在Agda中編寫這樣的swap
函數?
教授m == m + zero
Agda並不太難。 例如,使用標准類型進行相等證明,我們可以編寫此證明:
rightIdentity : (n : Nat) -> n + 0 == n
rightIdentity zero = refl
rightIdentity (suc n) = cong suc (rightIdentity n)
然后,我們可以使用rewrite
關鍵字告訴Agda使用此證明:
swap : {A : Set} {m n : Nat} -> Vec A (n + m) -> Vec A (m + n)
swap {_} {m} {zero} xs rewrite rightIdentity m = xs
swap {_} {_} {suc i} (x :: xs) = ?
但是,為第二個等式提供必要的證明要困難得多。 一般來說,嘗試使計算結構與類型結構相匹配是一個更好的主意。 這樣,你可以通過很少的定理證明(或在這種情況下沒有)。
例如,假設我們有
drop : {A : Set} {m : Nat} -> (n : Nat) -> Vec A (n + m) -> Vec A m
take : {A : Set} {m : Nat} -> (n : Nat) -> Vec A (n + m) -> Vec A n
(兩者都可以在沒有任何定理證明的情況下定義),Agda很樂意接受這個定義而不用大驚小怪:
swap : {A : Set} {m n : Nat} -> Vec A (n + m) -> Vec A (m + n)
swap {_} {_} {n} xs = drop n xs ++ take n xs
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.