2017-10-04 18 views
2

Je suis en train de calculer la parité avec le plancher de la moitié, sur des nombres naturels:Pourquoi ce bloc 'with' gâche-t-il la totalité de cette fonction?

data IsEven : Nat -> Nat -> Type where 
    Times2 : (n : Nat) -> IsEven (n + n) n 

data IsOdd : Nat -> Nat -> Type where 
    Times2Plus1 : (n : Nat) -> IsOdd (S (n + n)) n 

parity : (n : Nat) -> Either (Exists (IsEven n)) (Exists (IsOdd n)) 

J'ai essayé d'aller avec la mise en œuvre évidente de parity:

parity Z = Left $ Evidence _ $ Times2 0 
parity (S Z) = Right $ Evidence _ $ Times2Plus1 0 
parity (S (S n)) with (parity n) 
    parity (S (S (k + k))) | Left (Evidence _ (Times2 k)) = 
     Left $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2 (S k) 
    parity (S (S (S ((k + k))))) | Right (Evidence _ (Times2Plus1 k)) = 
     Right $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2Plus1 (S k) 

Ce typable et fonctionne comme attendu. Cependant, si je tente de marquer parity comme total, Idris commence à se plaindre:

parity is possibly not total due to: with block in parity 

Le seul with bloc que je vois dans parity est celui avec l'appel récursif de parity (S (S n)) à parity n, mais il est clair que bien-fondé, puisque n est structurellement plus petit que S (S n).

Comment puis-je convaincre Idris que parity est total?

+1

J'ai ouvert [numéro 4100] (https://github.com/idris-lang/ Idris-dev/issues/4100) sur GitHub. –

Répondre

2

Il ressemble à un bug pour moi, parce que la solution suivante basée sur case passe le vérificateur de la totalité:

total 
parity : (n : Nat) -> Either (Exists (IsEven n)) (Exists (IsOdd n)) 
parity Z = Left $ Evidence _ $ Times2 0 
parity (S Z) = Right $ Evidence _ $ Times2Plus1 0 
parity (S (S k)) = 
    case (parity k) of 
    Left (Evidence k (Times2 k)) => 
     Left $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2 (S k) 
    Right (Evidence k (Times2Plus1 k)) => 
     Right $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2Plus1 (S k) 
+0

Je peux confirmer que cette solution de contournement fonctionne pour mon problème dans la question d'origine - mais dans d'autres situations, un 'with' ne peut pas toujours être réécrit dans un' cas', n'est-ce pas? Je pense aux cas où la correspondance de motif affine les types d'autres arguments. – Cactus

+0

Droit! Voici une question connexe: https://stackoverflow.com/q/35610366/2747511. Nous avons de la chance que nous ayons des preuves dans le contexte. –

+0

Hmm, alors, est-ce que cela signifie que je devrais essayer de déplier manuellement ces 'avec' et voir si cela fonctionne? – Cactus