這是初學者在Idris混淆的常見話題。 在這種情況下,在第二conc
版本的問題:因爲納特加可交換是從視編譯點定理
conc : Vect n a -> Vect m a -> Vect (m+n) a
conc [] ys = ys
伊德里斯不能申請除交換性。在這裏它的類型:
Idris> :t plusCommutative
plusCommutative : (left : Nat) -> (right : Nat) -> left + right = right + left
有真不是一般的規則,告訴你哪個定理選擇和應用。當然,對於一些簡單的情況可以採用一些啓發式方法,如Nat交換性。但是這也會使其他一些情況難以理解。
你需要考慮的另一件事是plus
定義:
Idris> :printdef plus
plus : Nat -> Nat -> Nat
plus 0 right = right
plus (S left) right = S (plus left right)
功能plus
在一個這樣的方式定義做圖案的第一個參數匹配。 Idris實際上可以在類型中執行此模式匹配。因此,在第一個版本,其中
conc : Vect n a -> Vect m a -> Vect (n+m) a
conc [] ys = ys
你必須在類型和伊德里斯(0 + M)可與m
,一切typechecks更換plus 0 m
。如果你通過第二個參數的模式匹配來定義你+
運算符,那麼plus m 0
會起作用。例如,該編譯:
infixl 4 +.
(+.) : Nat -> Nat -> Nat
n +. Z = n
n +. (S m) = S (n +. m)
conc : Vect n a -> Vect m a -> Vect (m +. n) a
conc [] ys = ys
conc (x :: xs) ys = x :: (conc xs ys)
但很明顯,你需要每一種情況下編寫新的運營商是可怕的。因此,爲了使您的第二個版本可編譯,您應該使用Idris中的rewrite ... in
語法。您需要在下一個定理:
Idris> :t plusZeroRightNeutral
plusZeroRightNeutral : (left : Nat) -> left + 0 = left
Idris> :t plusSuccRightSucc
plusSuccRightSucc : (left : Nat) -> (right : Nat) -> S (left + right) = left + S right
Idris> :t sym
sym : (left = right) -> right = left
而這裏的版本,編譯:
conc : Vect n a -> Vect m a -> Vect (m + n) a
conc {m} [] ys = rewrite plusZeroRightNeutral m in ys
conc {n=S k} {m} (x :: xs) ys = rewrite (sym $ plusSuccRightSucc m k) in x :: (conc xs ys)
我不是在這裏解釋如何rewriting
和定理證明在這裏工作。如果你不瞭解某些事情,這是另一個問題的話題。但是你可以在教程中閱讀(或者等待The Book版本:)。
偉大的東西 - 這很清楚。實際上,我現在剛剛開始通過「The Book」開展工作,在MEAP出來時買了MEAP,但到現在還沒有時間通過它。 – FinnNk