Ceci est un sujet commun de confusion pour les débutants dans Idris. Le problème dans ce cas en deuxième version conc
:
conc : Vect n a -> Vect m a -> Vect (m+n) a
conc [] ys = ys
Idris ne peut pas appliquer plus commutativity parce que Nat, plus commutativity est un théorème du point de vue du compilateur. Voici son type:
Idris> :t plusCommutative
plusCommutative : (left : Nat) -> (right : Nat) -> left + right = right + left
Il sommes pas de règles générales pour vous dire que le théorème de choisir et d'appliquer. Bien sûr, certaines heuristiques peuvent être faites pour des cas simples, comme Nat commutativité. Mais cela peut aussi rendre difficile de comprendre certains autres cas.
L'autre chose que vous devez considérer est la définition de plus
:
Idris> :printdef plus
plus : Nat -> Nat -> Nat
plus 0 right = right
plus (S left) right = S (plus left right)
Fonction plus
définie de telle manière qui est fait sur son modèle correspondant premier argument. Idris effectivement peut effectuer ce type de correspondance dans les types. Ainsi, en première version, où
conc : Vect n a -> Vect m a -> Vect (n+m) a
conc [] ys = ys
vous avez (0 + m) type et Idris peut remplacer plus 0 m
avec m
et tout typable. plus m 0
fonctionnerait si vous définissiez +
opérateur par correspondance de modèle sur le second argument. Par exemple, cette compile:
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)
Mais il est évident que l'écriture nouvel opérateur pour tous les cas, vous avez besoin est horrible. Donc, pour faire votre deuxième version compilable vous devez utiliser la syntaxe rewrite ... in
dans Idris.Vous avez besoin théorèmes suivants:
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
Et voici la version qui compile:
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)
Je ne suis pas ici pour expliquer comment rewriting
et la démonstration de théorèmes fonctionne ici. C'est un sujet d'une autre question si vous ne comprenez pas quelque chose. Mais vous pouvez lire à ce sujet dans le tutoriel (ou attendre la sortie de The Book :).
De bonnes choses - c'est vraiment clair. Je suis en train de commencer à travailler sur 'The Book' en ce moment, j'ai acheté le MEAP quand il est sorti mais je n'avais pas pris le temps de le faire jusqu'à maintenant. – FinnNk