Haskell递归函数返回一个布尔



我正试图编写一个递归函数,将数字列表相加,并返回总和是否可被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) => f a -> 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类型,如MaybeTree等。

然而,如果值非常大,或者元素的数量非常大,这会给出不正确的结果,因为从那时起,总和就不能再用数字类型来表示了。然而,我们不需要计算全和,我们可以首先计算每个元素的(`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等效值(。我把这个留作练习。

相关内容

最新更新