【问题标题】:Need help understanding Haskell recursive division function需要帮助理解 Haskell 递归除法函数
【发布时间】:2021-12-26 06:19:41
【问题描述】:
recdiv :: Integer -> [Integer] -> [Integer] -> [Integer]
recdiv x numlist divisors
    | numlist == [] = divisors
    | mod x (last numlist) == 0 = recdiv x (init numlist) ((last numlist):divisors)
    | otherwise = recdiv x (init numlist) (divisors)

divides :: Integer -> [Integer]
divides x
    | x == 0 = error "Visi skaiciai"
    | x > 0 = recdiv x [1..x] []
    | x < 0 = recdiv (abs x) [1..(abs x)] []

这个函数的目的是找出输入数字的所有除数。

我了解在 divides 函数中会发生什么,但我在使用 recdiv 函数时遇到了一些问题。

据我所知,在第三行中,我们检查 numlist 是否为空,如果是,我们也将除数列表设为空。

但是,我无法真正理解第 4 行和第 5 行发生了什么。有人可以解释并帮助我理解吗?

【问题讨论】:

  • 这看起来是一种低效(且丑陋)的方法来确定除数。例如,last numlist 将在列表大小上花费线性时间。通常列表解包是在列表的头部和尾部完成的。
  • 也没有必要区分肯定论点和否定论点。只需使用绝对值。
  • 看起来recdiv 的调用方式是 1) 要被除的 x,2) 必须测试的潜在除数列表 numlist,以及 3) a列表divisors 包含到目前为止发现的除数。这不是最好的方法,而且代码在某种程度上写得不好(last==[]init 从来都不是一个好兆头)。

标签: haskell functional-programming


【解决方案1】:

这是一个更好的版本。

recdiv :: Integer -> [Integer] -> [Integer]
recdiv x numlist = case numlist of
    [] -> []
    y : ys
      | mod x y == 0 = y : recdiv x ys
      | otherwise = recdiv x ys

divides :: Integer -> [Integer]
divides 0 = error "Visi skaiciai"
divides x = recdiv (abs x) [1..(abs x)]

但是没有人会这样写recdiv;他们会使用

recdiv x = filter $ \y -> mod x y == 0

不要试图理解你正在查看的代码;扔掉吧。

【讨论】:

  • 我只为最后一句话投了赞成票。
猜你喜欢
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-15
  • 2021-11-29
相关资源
最近更新 更多