Haskell Mini功能实现

时间:2013-02-10 22:57:21

标签: haskell

我一直在尝试使用这个函数并使用iterate和takeWhile进行小型实现。它不必使用这些功能,我只是想把它变成一行。我可以在其中看到模式,但是我似乎无法在没有基本相同的代码的情况下利用它,只需使用迭代而不是递归。

fun2 :: Integer -> Integer
fun2 1 = 0
fun2 n 
    | even n = n + fun2 (n `div` 2)
    | otherwise = fun2 (3 * n + 1)

任何帮助都会很棒。几个小时以来我一直在努力。 感谢

3 个答案:

答案 0 :(得分:6)

如果你想用iterate做到这一点,关键是把它砍成更小的逻辑部分:

  • 使用规则生成序列

    a k + 1 = a k / 2如果 k 甚至

    a k + 1 = 3a k +1如果 k 奇数

  • j = 1处停止序列(如果collatz conjecture为真,则全部完成)。

  • 过滤掉路径上的偶数元素
  • 总结他们

那么这就变成了:

  f = sum . filter even . takeWhile (>1) . iterate (\n -> if even n then n `div` 2 else 3*n + 1)

但是,我确实认为使用帮助函数会更清楚

  f = sum . filter even . takeWhile (>1) . iterate collatz
    where collatz n | even n    = n `div` 2
                    | otherwise = 3*n + 1

这可能不会为您节省任何行,但会将您的递归转换为数据生成。

答案 1 :(得分:3)

首先,我同意汤姆的评论,即你的四行版本没有任何问题。它完全可读。但是,将Haskell函数转换为一个衬里偶尔会很有趣。谁知道,你可能会学到一些东西!

目前你有

fun 1 = 0
fun n | even n    = n + fun (n `div` 2)
      | otherwise = fun (3 * n + 1)

您始终可以使用警卫将表达式转换为if

fun 1 = 0
fun n = if even n then n + fun (n `div` 2) else fun (3 * n + 1)

您始终可以将一系列模式匹配转换为案例表达式:

fun n = case n of
            1 -> 0
            _ -> if even n then n + fun (n `div` 2) else fun (3 * n + 1)

最后,你可以将case表达式转换为if s的链(实际上,通常这需要一个Eq实例作为函数的参数,但是因为你正在使用Integer这没关系。)

fun n = if n == 1 then 0 else if even n then n + fun (n `div` 2) else fun (3 * n + 1)

我认为你会同意这比你开始时的可读性差得多。

答案 2 :(得分:0)

一个班轮;)

fun2 n = if n==1 then 0 else if even n then n + fun2 (n `div` 2) else fun2 (3 * n + 1)

我的感觉是缺少查找表,没有递归就无法实现此函数,因为在递归中传递的参数似乎是不可预测的(除了n为2的幂)。

另一方面,猖獗让我学到了新的东西。