# [Haskell-beginners] PI calculation - Newbie question

Felipe Lessa felipe.lessa at gmail.com
Fri Jan 29 07:32:08 EST 2010

```On Fri, Jan 29, 2010 at 12:59:30PM +0200, Gabi wrote:
> I think the problem is in  "rs <- sequence (replicate n isRandIn)"  -
> But I don't know how to get around it (how do I get a lazy sequence of
> rs? Is it the problem anyway?)

First of all, we don't like to be inside IO just for getting
random numbers.  It is better to write, for example,

type Point = (Double, Double)

randPoint :: StdGen -> (Point, StdGen)
randPoint gen = let (x, gen')  = randomR (0,1) gen
(y, gen'') = randomR (0,1) gen'
in ((x,y),gen'')

and then thread the generator yourself

randPoints :: StdGen -> [Point]
randPoints gen = let (p,gen') = randPoint gen
in p : randPoints gen' -- lazy!

To use those functions, something like

import Control.Applicative ((<\$>))

inCirc :: Point -> Bool
inCirc = ...

calcPi :: Int -> [Point] -> Double
calcPi n pts = let s = length \$ filter inCirc \$ take n pts
in 4 * fromIntegral s / fromIntegral n

main = do pi <- calcPi 10000 . randPoints <\$> newStdGen
print pi

I haven't tested performance, but it shouldn't be worse :), and
it's cleaner and more idiomatic.  To be even clearer you could
use MonadRandom which encapsulates the passing of StdGen between
computations.

However System.Random (used by MonadRandom as well) is known to
be very very very very slow.  If you want more performance then
you should use one of the other PRNG libraries on Hackage: