在尝试学习 Haskell 时,我实现了一个 pi 计算,以便正确理解函数和递归。
使用莱布尼茨公式计算 pi,我想出了以下内容,它将 pi 打印到给定参数的容差,以及递归函数调用的次数以获得该值:
reverseSign :: (Fractional a, Ord a) => a -> a
reverseSign num = ((if num > 0
then -1
else 1) * (abs(num) + 2))
piCalc :: (Fractional a, Integral b, Ord a) => a -> (a, b)
piCalc tolerance = piCalc' 1 0.0 tolerance 0
piCalc' :: (Ord a, Fractional a, Integral b) => a -> a -> a -> b -> (a, b)
piCalc' denom prevPi tolerance count = if abs(newPi - prevPi) < tolerance
then (newPi, count)
else piCalc' (reverseSign denom) newPi tolerance (count + 1)
where newPi = prevPi + (4 / denom)
因此,当我在 GHCI 中运行它时,它似乎按预期工作:
*Main> piCalc 0.001
(3.1420924036835256,2000)
但是,如果我将容差设置得太细,就会发生这种情况:
*Main> piCalc 0.0000001
(3.1415927035898146,*** Exception: stack overflow
这对我来说似乎完全违反直觉。实际计算工作正常,但只是试图打印多少递归调用失败?
为什么会这样?