I have three functions in Haskell. All of them are meant to be perform √2 based on an initial guess for n iterations.
squareRootTwo :: Double -> Integer -> Double
squareRootTwo guess n
| n == 0 = guess
| otherwise = squareRootTwo ((guess + 2/guess) / 2) (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
The first function (squareRootTwo) is working fine. In ghci:
ghci> squareRootTwo 1.0 5
1.414213562373095
ghci> squareRootTwoA 1.0 5
No response
ghci> squareRootTwoB 1.0 5
No response
But the second and the third function aren't working at all. They just frezees. I had to press (ctrl + c) to stop this in VS Code terminal. Now, I understand maybe it's creating a recursion and falls into a infinite loop. But, I don't understand how it's creating a infinite loop. Because the way both programs are written, to me it seems like it's not creating a infinite loop.
Since I'm new to the Haskell, I just don't understand why is this happening.
Your definitions are equivalent to the following:
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
You see that the integer argument in the recursive call has in both cases nothing at all to do with the original value n, it's a completely new variable that just happens to have the same name and shadows the old n. And a definition like n = n-1 is of course circular, it's an equation that can't possibly be fulfilled (other languages are mathematically lying to you when they execute this as a statement).
The way to achieve what you attempted is to explicitly give the new version a different name:
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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With