Cale Gibbard cgibbard at gmail.com
Tue Jul 19 18:35:31 EDT 2005

```To get exact fractions, use the Ratio module (import Ratio) and the
Rational type which is defined there.

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:

f x = let t = 2 * x
in if t < 1
then t
else t - 1

or with guards:

f x | t < 1 = t
| otherwise = t - 1
where t = 2 * x

Note that there isn't any problem with using pure functions from the
IO monad. You can write gen as follows:

gen :: Double -> IO ()
gen x | c == 0.0 = return ()
| otherwise = do putStrLn \$ "Value is: " ++ show c; gen c
where c = f x

(writeln is called putStrLn in the standard prelude)

Or syntactically closer to your original code:

gen :: Double -> IO ()
gen x = do let c = f x
putStrLn ("Value  is: " ++ show c)
if (c /= 0.0)
then gen c
else return ()

You don't use the c <- f x notation because (f x) is directly the
value you want, not an IO action which executes to produce that value.

So long as you don't put a type signature on it (causing it to get
inferred), or if you give it the type signature:
f :: (Num a, Ord a) => a -> a
it will work with any ordered type of numbers, which allows you to
load up the Ratio module in ghci (":m + Ratio") and try it with things
like 1%3 (which represents one-third exactly).

Hope this is useful,
- Cale

On 19/07/05, Dinh Tien Tuan Anh <tuananhbirm at hotmail.com> wrote:
> Here's what i got
>
> writeln x = putStr (x++ "\n")
>
> f:: Double -> IO Double
> f x = do
>         let t = 2*x
>         if (t<1)
>         then return t
>         else return (t-1)
>
>
> gen :: Double -> IO()
> gen x = do c<-f x
>            writeln ("Value  is: " ++ show c)
>            if (c /= 0.0)
>                 then  gen c
>                 else  return ()
>
-snip-
```