Haskell递归堆栈溢出

时间:2015-05-24 00:20:18

标签: haskell recursion stack-overflow guard

我对Haskell很新,很抱歉这个问题。但是 - 如何摆脱无休止的递归而不是溢出。这是代码:

foo :: Integer -> Integer
foo x
    | x == 1         = 1
    | x <= 0         = error "negative number or zero"
    | odd x          = foo 3 * x + 1
    | x `mod` 2 == 0 = foo x `div` 2
    | otherwise      = x

修改

foo :: Integer -> (Integer, Integer)
foo x
    | x == 1         = (1, z) 
    | x <= 0         = error "negative number or zero"
    | odd x          = foo  (3 * x + 1) . inc z
    | even x         = foo  (x `div` 2) . inc z
    | otherwise      = (x, z)
  where z = 0

inc :: Integer -> Integer
inc i = i + 1

我相信代码是不言自明的,但是:如果x是偶数,那么将它除以2,否则为3 * x + 1.这是着名的Collat​​z问题的一部分。

1 个答案:

答案 0 :(得分:5)

函数应用程序的优先级高于许多其他操作,因此foo 3 * x + 1实际上调用foo 3,然后将结果乘以x并添加1,这看起来就像在哪里你的无限循环可能是。

将其更改为以下内容应该可以解决:

| odd x          = foo $ 3 * x + 1
| x `mod` 2 == 0 = foo $ x `div` 2