[Haskell-cafe] Help with IO and randomR
Bryan Burgers
bryan.burgers at gmail.com
Mon Jul 16 08:31:03 EDT 2007
On 7/16/07, Niko Korhonen <niko.korhonen at gmail.com> wrote:
> I'm writing some code to generate a dither (=noise) signal. I'm trying
> to generate an infinite series of noise with triangular distribution but
> my code hangs into an infinite loop. The problem is that I'm not very
> good with Haskell IO yet and I can't figure out how to write this piece
> of IO code without it looping infinitely.
>
> So, in short, how do I do this without getting into an infinite loop:
>
> tpdfs :: (Int, Int) -> IO [Int]
> tpdfs (low, high) = do
> first <- getStdRandom (randomR (low, high))
> second <- getStdRandom (randomR (low, high))
> let r = (first + second) `div` 2
> rest <- tpdfs (low, high)
> return (r : rest)
>
> Caller site:
>
> do
> nums <- tpdfs (2, 12)
> let ns = take 7 nums
>
> Niko
I did not look at it long enough to tell you why there is an infinite
loop. However, think about it on a high level with me.
You want a stream of these random numbers (I'm not sure what a
triangular distribution is, but that's okay). To get one of these, you
take two random numbers and perform a combination function (\x y -> (x
+ y) `div` 2 ) on them.
So you can lift this from one random numbers to a stream of random
numbers if you have have two streams of random numbers instead of just
two random numbers. zipWith is the function that brings us from one
number to a stream of numbers.
tpdfs range = do
g <- newStdGen -- get a random generator
(g1, g2) <- return $ split g -- make two random generators out of it
return $ zipWith combine (randomRs range g1) (randomRs range g2)
-- get two streams of random numbers, and combine them elementwise.
combine x y = (x + y) `div` 2
Uh, I know that's a very poor explanation, but hopefully it gives you
an alternate way to look at the problem.
More information about the Haskell-Cafe
mailing list