Determine if Sum of Vect n Nat's Evenly Divides 5?

爷,独闯天下 提交于 2019-12-11 13:06:48

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!