2017-10-06 7 views
4

inductive Considérons la fonction suivanteIdris - preuve à l'étape

tryMove : (diskNumber : Nat) -> (from: Peg) -> (to: Peg)-> {default Oh prf: So (from /= to)} -> Disposition diskNumber -> Maybe (Disposition diskNumber) 
tryMove Z from to [] = Nothing 
tryMove (S k) from to (smallestDiskPosition :: restOfTheDisposition) = 
     map (smallestDiskPosition ::) (tryMove k from to restOfTheDisposition) 

Essayer de compiler je reçois l'erreur suivante:

When checking argument prf to Hanoi.tryMove: 
     Type mismatch between 
       So True (Type of Oh) 
     and 
       So (from /= to) (Expected type) 

     Specifically: 
       Type mismatch between 
         True 
       and 
         not (Hanoi.Peg implementation of Prelude.Interfaces.Eq, method == from to) 

sur l'invocation de recurvise de tryMove. Si je passe comme dans {prf} explicitement

tryMove : (diskNumber : Nat) -> (from: Peg) -> (to: Peg)-> {default Oh prf: So (from /= to)} -> Disposition diskNumber -> Maybe (Disposition diskNumber) 
tryMove Z from to [] = Nothing 
tryMove (S k) from to {prf} (smallestDiskPosition :: restOfTheDisposition) = 
     map (smallestDiskPosition ::) (tryMove k from to {prf} restOfTheDisposition) 

Il compile correctement.

Pourquoi est-ce que Idris ne peut pas détecter automatiquement la preuve dans l'étape inductive, alors qu'il est capable de le faire dans une invocation normale de la fonction?

EDIT:

ici est un point essentiel complet à utiliser: https://gist.github.com/marcosh/d51479ea08e8522560713fd1e5ca9624

Répondre

4

Vous fournissez la valeur par défaut (Oh) pour prf, si Idris tente de passer Oh dans l'appel récursif. Oh est de type So True et Idris attend prf être de type So (from /= to), mais puisque vous ne Destruct to et from, Idris ne peut pas connaître la valeur de from /= to, c'est pourquoi vous voyez ce message d'erreur.

Vous pouvez modifier la signature pour qu'elle contienne {auto prf: So (from /= to)} ou supprimer complètement l'argument prf, car vous ne l'utilisez pas réellement, vous le transmettez simplement dans l'appel récursif sans aucune modification.

+0

merci pour votre réponse. Je ne comprends pas une chose. Que voulez-vous dire par «puisque vous ne détruisez pas de et vers, Idris ne peut pas connaître la valeur de/= to'? 'from' et' to' restent identiques à l'appel initial. Si elles sont différentes au début, pourquoi Idris ne peut-il pas comprendre qu'elles sont différentes après? De plus, que voulez-vous dire par détruire 'to' et' from'? Comment pourrais-je faire ça? – marcosh

+0

Vous passez 'Oh' de type' So True' où Idris attend une valeur de type 'So (de/= to)', Idris vous permettra de le faire tant que 'from/= to' et' True' sont définition égale, ou plus précise dans ce cas si 'from/= to' est évalué à' True'. Mais pour évaluer l'application de la fonction '(/ =)', vous devez savoir exactement ce que sont les deux arguments. Idris ne sait pas que 'from' et' to' ne sont pas égaux. L'appariement de motifs est la manière dont vous propagez l'information. Donc, une façon extrêmement moche d'aider Idris serait de faire correspondre pattern sur 'from' et' to' - cela générerait 9 clauses (dont 3 sont impossibles) –