2016-04-12 7 views
1

Cactus demonstriert, wie ich meine Frage: Helper Function to Determine if Nat `mod` 5 == 0.Ermitteln, ob die Summe von Vect n Nat gleich 5 teilt?

Er schrieb:

onlyModBy5 : (n : Nat) -> {auto prf : n `modNat` 5 = 0} -> Nat 
onlyModBy5 n = n 

Dann habe ich diese Funktion zu nutzen versucht anzuwenden onlyModBy5 auf die Summe von Vect n Nat ‚s.

foo : (n : Nat) -> Vect n Nat -> Nat 
foo n xs = onlyModBy5 $ sum xs 

Aber ich habe diesen Fehler bei der Kompilierung:

When checking right hand side of foo with expected type 
     Nat 

When checking argument prf to function Main.onlyModBy5: 
     Can't find a value of type 
       Prelude.Nat.modNatNZ, mod' (foldrImpl (\meth => 
                 \meth => 
                  plus meth meth) 
                 0 
                 id 
                 xs) 
              4 
              SIsNotZ 
              (foldrImpl (\meth => 
                 \meth => 
                  plus meth meth) 
                 0 
                 id 
                 xs) 
              (foldrImpl (\meth => 
                 \meth => 
                  plus meth meth) 
                 0 
                 id 
                 xs) 
              4 = 
       0 
Holes: Main.foo 

Wie kann ich die oben onlyModBy5 Funktion mit foo verwenden?

Antwort

2

Es hängt davon ab, was Sie erreichen möchten. foo : (n : Nat) -> Vect n Nat -> Nat sagt, dass Sie jede Nat zu foo anwenden können, und jede Vect von Nat (wenn die Vect der Größe ist n) und foo eine Nat zurück.

Zunächst einmal brauchen Sie nicht das explizite (n : Nat) Argument. Wenn Sie nur foo : Vect n Nat -> Nat schreiben, würde Idris n intern in ein implizites Argument: foo : {n : Nat} -> Vect n Nat -> Nat.

In den Argumenten ist nichts über die Elemente der Vect, und daher nichts über die sum davon. Sie könnten [1,2,2] sowie [1,1] anwenden, während letzterer keinen Beweis von prf : (sum [1,1])`modNat`5 == 0) hat, so offensichtlich können Sie die Summe nicht auf onlyModBy5 anwenden.

Sie entweder einen Beweis dafür als Argument wie vor verlangen könnte:

bar : (xs : Vect n Nat) -> {auto prf : (sum xs) `modNat` 5 = 0} -> Nat 
bar xs = onlyModBy5 (sum xs) 

Oder lassen Sie es auf der Grundlage der Summe entscheiden:

foo : Vect n Nat -> Maybe Nat 
foo xs = foo' (sum xs) 
    where 
    foo' : Nat -> Maybe Nat 
    foo' k with (decEq (k `modNat` 5) 0) 
     | Yes prf = Just (onlyModBy5 k {prf}) 
     | No _ = Nothing 

decEq entscheidet, ob zwei Werte propositionally gleich sind (in diesem Fall, wenn sie gleich sind Nat), und entweder Yes mit einer (prf : n`modNat`5 = 0), dass sie gleich sind, oder No mit einem Beweis, dass sie nicht gleich sind. Dieser Nachweis kann dann onlyModBy5 mit {prf} gegeben werden. Dies erstreckt sich auf {prf=prf}, was das implizite Argument zum Beweis von Yes gibt, da beide prf genannt werden.

+1

Ich denke, du könntest 'foo' etwas verbessern, indem du explizit' prf' zu 'onlyModBy5k' übertriffst, um die Tatsache zu betonen, dass der Beweis jetzt kommt. – Cactus