【问题标题】:Haskell Recursive Function Returning One BoolHaskell 递归函数返回一个布尔值
【发布时间】:2021-01-06 09:50:57
【问题描述】:

我正在尝试编写一个递归函数来将一个数字列表相加并返回一个 Bool 总和是否可被 5 整除。但是,我无法让它工作。

div5 :: [Int] -> Bool 
div5 (x:xs)  
  | total `mod` 5 == 0 = True
  | otherwise = False
  where
    total = total + x

【问题讨论】:

  • total = total + x,没有多大意义。它将创建一个无限循环来评估它。

标签: haskell recursion pattern-matching


【解决方案1】:

表达式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 等效项)。我把它留作练习。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-12
    • 1970-01-01
    • 2015-02-08
    • 1970-01-01
    • 2018-08-02
    • 2020-07-25
    • 1970-01-01
    • 2019-04-27
    相关资源
    最近更新 更多