为了练习Haskell,我实施了Fermat的分解方法(参见https://en.wikipedia.org/wiki/Fermat%27s_factorization_method)。但是,当我运行我的程序时,Haskell一直告诉我:
$ ./fermat 7
fermat: <<loop>>
所以看来,我的代码中存在无限循环(cmp。http://www.haskell.org/pipermail/haskell-cafe/2013-June/108826.html)。谁能给我一个提示,我做错了什么?
此外,我想扩展问题How to debug Haskell code?,以获取有关如何调试此特定异常的提示。
import Data.List
import System.Environment
import Debug.Trace
isQuad :: Integer -> Bool
isQuad x = a == b
where
a = ceiling $ s
b = floor $ s
s = sqrt (fromIntegral x :: Double)
test :: Integer -> Integer -> Integer -> Bool
test nr n s = trace(show nr ++ " " ++ show n ++ " " ++ show s)
isQuad(
(+)
( (\j -> j * j) s + nr )
(-n)
)
fermat :: Integer -> (Integer, Integer)
fermat n = (s + x, s - x)
where
s = ceiling $ sqrt (fromIntegral x :: Double)
r = trace
(show s ++ " " ++ show n)
(\(Just i) -> i) $
find
(\nr -> test nr n s)
[0..n]
x = floor $ sqrt (fromIntegral r :: Double)
fact :: Integer -> (Integer, Integer)
fact x
| x == 1 = (1, 1)
| even x = (2, x `div` 2)
| otherwise = fermat x
f :: String -> String
f x = x ++ " = " ++ show a ++ " x " ++ show b
where
(a, b) = fact $ (read x :: Integer)
main = do
args <- getArgs
putStrLn $ unlines $ map f args
答案 0 :(得分:5)
在fermat
中,s
取决于x
,x
取决于r
,r
取决于s
。
有时懒惰可能会使这种循环依赖性正常,但在这种情况下,所有依赖关系似乎都是严格的。
这只是来自检查,除了链接帖子之外,我对如何调试问题没有任何特别的建议。
我会说<<loop>>
意味着运行时系统能够检测到无限循环,这意味着值取决于它自身,例如let x = x + 1 in x
。所以这是追踪问题的一点线索。
如果你在函数调用中写了一个无限循环,例如let f x = f x + 1 in f 1
,它通常会永远运行。有时优化器可能会将这些函数调用转换为值,但一般情况下不能这样做。