Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random number sequence un Haskell and State Monad, what am I doing wrong?

As part of my Haskell journey, I am implementing a raytracer and I need to be able to draw sequences of random numbers at several places in the code. Typically I would like to be able to get say 64 samples for each pixels and pixels are computed in parallel.

I was looking at the state monad to achieve that and I was guided by this answer Sampling sequences of random numbers in Haskell but the code I wrote does not terminate and it's memory consumption explodes.

Here is the abstracted part of the code: I was hopping to be able to call sampleUniform several time in the code to get new lists of random numbers but if I do runhaskell test.hs, it outputs the first character of the lis [ and then it is stuck in an apparently infinite loop.

module Main (main
            , computeArray) where

import Control.Monad
import Control.Monad.State (State, evalState, get, put)
import System.Random (StdGen, mkStdGen, random)
import Control.Applicative ((<$>))

type Rnd a = State StdGen a

runRandom :: Rnd a -> Int -> a
runRandom action seed = evalState action $ mkStdGen seed

rand :: Rnd Double
rand = do
  gen <- get
  let (r, gen') = random gen
  put gen'
  return r

{- Uniform distributions -}
uniform01 :: Rnd [Double]
uniform01 = mapM (\_ -> rand) $ repeat ()

{- Get n samples uniformly distributed between 0 and 1 -}
sampleUniform :: Int -> Rnd [Double]
sampleUniform n = liftM (take n) uniform01

computeArray :: Rnd [Bool]
computeArray = do
  samples1 <- sampleUniform 10
  samples2 <- sampleUniform 10
  let dat = zip samples1 samples2
  return $ uncurry (<) <$> dat

main :: IO ()
main = do
  let seed = 48
  let res = runRandom computeArray seed
  putStrLn $ show res
like image 847
overlii Avatar asked Aug 08 '15 11:08

overlii


People also ask

Why use state monad?

@ais The State type is simply a wrapper around argument passing with a tuple returned. The purpose of using it is to have a better defined set of functions, where you basically say "All of these functions are designed to work together", and to reduce the amount of typing you need to do.

What is state monad?

The state monad is a built in monad in Haskell that allows for chaining of a state variable (which may be arbitrarily complex) through a series of function calls, to simulate stateful code.


1 Answers

uniform01 threads your state through an infinite number of computations, which means that although it produces its result lazily, there is no hope of retrieving a final state at the end to use for the next sampling. liftM (take n) only affects the final value, not the state effects used to compute it. Therefore as written, you can only use uniform01/sampleUniform once.

Instead you can thread the state through only as many rand actions as you use, e.g. with

sampleUniform n = mapM (\_ -> rand) $ replicate n ()

or simpler

sampleUniform n = sequence $ replicate n rand
like image 143
Ørjan Johansen Avatar answered Oct 17 '22 02:10

Ørjan Johansen