确定 Vect n Nat 的总和是否能整除 5?
Determine if Sum of Vect n Nat's Evenly Divides 5?
Cactus demonstrated how to address my question: .
他写道:
onlyModBy5 : (n : Nat) -> {auto prf : n `modNat` 5 = 0} -> Nat
onlyModBy5 n = n
然后,我尝试使用该函数将 onlyModBy5
应用于 Vect n Nat
的总和。
foo : (n : Nat) -> Vect n Nat -> Nat
foo n xs = onlyModBy5 $ sum xs
但是我得到了这个编译时错误:
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
如何将上述 onlyModBy5
函数与 foo
一起使用?
这取决于你想要达到的目标。 foo : (n : Nat) -> Vect n Nat -> Nat
表示您可以将任何 Nat
应用于 foo
,以及 Nat
的任何 Vect
(如果 Vect
的大小为 n
) 和 foo
将 return 一个 Nat
.
首先,您不需要明确的 (n : Nat)
参数。如果你只写 foo : Vect n Nat -> Nat
,Idris 会在内部将 n
变成一个隐式参数:foo : {n : Nat} -> Vect n Nat -> Nat
.
参数中没有关于 Vect
的元素,因此也没有关于它的 sum
的元素。您也可以应用 [1,2,2]
以及 [1,1]
,而后者没有 prf : (sum [1,1])
`modNat`
5 == 0)
的证明,因此显然您不能应用总和为 onlyModBy5
.
您可以像以前一样要求证明这一点作为论据:
bar : (xs : Vect n Nat) -> {auto prf : (sum xs) `modNat` 5 = 0} -> Nat
bar xs = onlyModBy5 (sum xs)
或者让它根据总和来决定:
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
决定两个值在命题上是否相等(在这种情况下,如果它们相同 Nat
),以及 return 或 Yes
与 (prf : n
`modNat`
5 = 0)
它们相等,或 No
证明它们不相等。然后可以用 {prf}
将此证明提供给 onlyModBy5
。这扩展到 {prf=prf}
,它为隐式参数提供 Yes
的证明,因为两者都被命名为 prf
.
Cactus demonstrated how to address my question:
他写道:
onlyModBy5 : (n : Nat) -> {auto prf : n `modNat` 5 = 0} -> Nat
onlyModBy5 n = n
然后,我尝试使用该函数将 onlyModBy5
应用于 Vect n Nat
的总和。
foo : (n : Nat) -> Vect n Nat -> Nat
foo n xs = onlyModBy5 $ sum xs
但是我得到了这个编译时错误:
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
如何将上述 onlyModBy5
函数与 foo
一起使用?
这取决于你想要达到的目标。 foo : (n : Nat) -> Vect n Nat -> Nat
表示您可以将任何 Nat
应用于 foo
,以及 Nat
的任何 Vect
(如果 Vect
的大小为 n
) 和 foo
将 return 一个 Nat
.
首先,您不需要明确的 (n : Nat)
参数。如果你只写 foo : Vect n Nat -> Nat
,Idris 会在内部将 n
变成一个隐式参数:foo : {n : Nat} -> Vect n Nat -> Nat
.
参数中没有关于 Vect
的元素,因此也没有关于它的 sum
的元素。您也可以应用 [1,2,2]
以及 [1,1]
,而后者没有 prf : (sum [1,1])
`modNat`
5 == 0)
的证明,因此显然您不能应用总和为 onlyModBy5
.
您可以像以前一样要求证明这一点作为论据:
bar : (xs : Vect n Nat) -> {auto prf : (sum xs) `modNat` 5 = 0} -> Nat
bar xs = onlyModBy5 (sum xs)
或者让它根据总和来决定:
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
决定两个值在命题上是否相等(在这种情况下,如果它们相同 Nat
),以及 return 或 Yes
与 (prf : n
`modNat`
5 = 0)
它们相等,或 No
证明它们不相等。然后可以用 {prf}
将此证明提供给 onlyModBy5
。这扩展到 {prf=prf}
,它为隐式参数提供 Yes
的证明,因为两者都被命名为 prf
.