
On 7/19/05, Cale Gibbard
The code you wrote below has a serious style problem that I thought I'd point out: you shouldn't use the IO monad for pure functions. You can define f as follows: [snip]
I agree on the stylistic front. Another approach is to make the generator function return the list of values. gen :: Double -> [Double] gen x = (takeWhile (/= 0.0) $ iterate f x) ++ [0.0] where f x = let t = 2 * x in if t < 1 then t else t-1 showSteps :: [Double] -> [String] showSteps xs = map showStep $ zip [1..] xs where showStep (n, x) = (show n) ++ ". Value is: " ++ (show x) iogen :: Double -> IO () iogen x = mapM_ putStrLn $ showSteps $ gen x I added the ++ [0.0] to gen so that it will generate the same list as the original version. To illustrate the generality of the floating-point inexactness problem, I added the step numbering to compare with another programming language. In Python: def gen(x, n=1): t = x * 2. if t < 1.: c = t else: c = t - 1 print '%d. Value is: %.16f' % (n, c) if c != 0: gen(c, n + 1) Both programs terminate in the same number of steps, since their floating-point types have the same underlying implementation. Python has no Rational type to fall back on, however. Josh Hoyt