问题
Cactus demonstrated how to address my question: Helper Function to Determine if Nat `mod` 5 == 0.
He wrote:
onlyModBy5 : (n : Nat) -> {auto prf : n `modNat` 5 = 0} -> Nat
onlyModBy5 n = n
Then, I attempted to use that function to apply onlyModBy5
to the sum of a Vect n Nat
's.
foo : (n : Nat) -> Vect n Nat -> Nat
foo n xs = onlyModBy5 $ sum xs
But I got this compile-time error:
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
How can I use the above onlyModBy5
function with foo
?
回答1:
It depends on what you want to achieve. foo : (n : Nat) -> Vect n Nat -> Nat
says that you can apply any Nat
to foo
, and any Vect
of Nat
(if the Vect
is of size n
) and foo
will return a Nat
.
First off, you don't need the explicit (n : Nat)
argument. If you write just foo : Vect n Nat -> Nat
, Idris would turn n
internally into an implicit argument: foo : {n : Nat} -> Vect n Nat -> Nat
.
In the arguments is nothing about the elements of the Vect
, and therefor nothing about the sum
of it. You could apply [1,2,2]
as well [1,1]
, whereas the latter doesn't have a proof of prf : (sum [1,1])
`modNat`
5 == 0)
, so obviously you can't apply the sum to onlyModBy5
.
You could either demand a proof of this as an argument as before:
bar : (xs : Vect n Nat) -> {auto prf : (sum xs) `modNat` 5 = 0} -> Nat
bar xs = onlyModBy5 (sum xs)
Or let it decide based on the sum:
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
decides whether two values are propositionally equal (in this case, if they are the same Nat
), and either returns Yes
with a (prf : n
`modNat`
5 = 0)
that they are equal, or No
with a proof that they aren't equal. This proof can be then given to onlyModBy5
with {prf}
. This extends to {prf=prf}
, which gives the implicit argument the proof of Yes
, as both are named prf
.
来源:https://stackoverflow.com/questions/36562497/determine-if-sum-of-vect-n-nats-evenly-divides-5