[英]Haskell Recursive Function Returning One Bool
我正在尝试编写一个递归函数来将一个数字列表相加并返回一个关于总和是否可以被 5 整除的Bool
。但是,我无法让它工作。
div5 :: [Int] -> Bool
div5 (x:xs)
| total `mod` 5 == 0 = True
| otherwise = False
where
total = total + x
表达式where total = total + x
没有多大意义,在评估这个时会导致无限循环,因为你说total
等价于total + x
,因此(total + x) + x
, ((total + x) + x) + x
等。
一个简单的解决方案是利用sum :: (Foldable f, Num a) => fa -> a
对数字求和,然后检查结果是否等于0
:
div5 :: (Foldable f, Integral a) => f a -> Bool
div5 xs = mod (sum xs) 5 == 0
或以无点符号表示:
div5 :: (Foldable f, Integral a) => f a -> Bool
div5 = (0 ==) . (`mod` 5) . sum
例如:
Prelude Data.List> div5 [1,4,2,5]
False
Prelude Data.List> div5 [1,4,2,5,3]
True
这不仅适用于列表,还适用于所有Foldable
类型,因此Maybe
、 Tree
等。
然而,如果值非常大,或者元素数量非常大,这会给出不正确的结果,因为这样总和不能再由数字类型表示。 然而,我们不需要计算全和,我们可以先计算每个元素的(`mod` 5)
,然后将其求和,其中每个和再次是mod 5
,然后我们得到和mod 5
的结果,并且因此我们可以检查这是否为 0:
import Data.List(foldl')
div5 :: (Foldable f, Integral a) => f a -> Bool
div5 xs = foldl' f 0 xs == 0
where f y = (`mod` 5) . (y+) . (`mod` 5)
您可以将其转换为带有辅助函数的递归函数,该函数执行递归以求和值(或它们的模块 5 等效项)。 我把它留作练习。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.