Ani*_*der 3 recursion haskell infinite-loop
我在 Haskell 中有三个函数。所有这些都旨在基于 n 次迭代的初始猜测来执行 \xe2\x88\x9a2 。
\nsquareRootTwo :: Double -> Integer -> Double\nsquareRootTwo guess n\n| n == 0 = guess\n| otherwise = squareRootTwo ((guess + 2/guess) / 2) (n-1)\nRun Code Online (Sandbox Code Playgroud)\nsquareRootTwoA :: Double -> Integer -> Double\nsquareRootTwoA guess n\n| n == 0 = guess\n| otherwise = squareRootTwoA ((guess + 2/guess) / 2) (n-1) where n=n\nRun Code Online (Sandbox Code Playgroud)\nsquareRootTwoB :: Double -> Integer -> Double\nsquareRootTwoB guess n\n| n == 0 = guess\n| otherwise = let n = n-1 in squareRootTwoB ((guess + 2/guess) / 2) n\nRun Code Online (Sandbox Code Playgroud)\n第一个函数(squareRootTwo)工作正常。在 ghci 中:
\nghci> squareRootTwo 1.0 5 \n1.414213562373095\n\nghci> squareRootTwoA 1.0 5\nNo response\nghci> squareRootTwoB 1.0 5\nNo response\nRun Code Online (Sandbox Code Playgroud)\n但第二个和第三个功能根本不起作用。他们只是冻结了。我必须在 VS Code 终端中按 ( ctrl+ c) 来停止此操作。\n现在,我明白它可能正在创建递归并陷入无限循环。但是,我不明白它是如何创建无限循环的。因为这两个程序的编写方式,对我来说似乎并没有创建无限循环。
\n由于我是 Haskell 的新手,我只是不明白为什么会发生这种情况。
\n您的定义等效于以下内容:
squareRootTwoA :: Double -> Integer -> Double
squareRootTwoA guess n
| blurb == 0 = guess
| otherwise = squareRootTwoA ((guess + 2/guess) / 2) (blurb-1)
where blurb = blurb
squareRootTwoB :: Double -> Integer -> Double
squareRootTwoB guess n
| n == 0 = guess
| otherwise = let blurb = blurb-1
in squareRootTwoB ((guess + 2/guess) / 2) blurb
Run Code Online (Sandbox Code Playgroud)
您会看到,递归调用中的整数参数在这两种情况下都与原始值没有任何关系n,它是一个全新的变量,只是碰巧具有相同的名称并隐藏了旧的变量n。像这样的定义n = n-1当然是循环的,它是一个不可能满足的方程(当其他语言将其作为语句执行时,它们在数学上对你撒谎)。
实现您尝试的方法是显式地为新版本指定一个不同的名称:
squareRootTwoA :: Double -> Integer -> Double
squareRootTwoA guess n
| n == 0 = guess
| otherwise = squareRootTwoA ((guess + 2/guess) / 2) (n'-1)
where n' = n
squareRootTwoB :: Double -> Integer -> Double
squareRootTwoB guess n
| n == 0 = guess
| otherwise = let n' = n-1
in squareRootTwoB ((guess + 2/guess) / 2) n'
Run Code Online (Sandbox Code Playgroud)