Shin-Cheng Mu wrote:

 | Undoubtedly you can write your own monad and encapsulate
 | the random number generation yourself. It is just an 
 | instance of a state monad.

A state monad has (like you say) the disadvantage that it is
single threaded. A big problem then is laziness; it becomes
impossible to generate infinite structures
(like trees) independently.

A different approach is to define a random number generating
monad in the following way:

  newtype R a =
    R (StdGen -> a)

  instance Monad R where
    return x =
      R (\_ -> x)

    R m1 >>= k =
      R (\rnd -> let (rnd1, rnd2) = split rnd
                     R m2         = k (m1 rnd1)
                  in m2 rnd2)

  get :: R StdGen
  get = R (\rnd -> rnd)

The random seed is distributed from the top over all
subcomputations. This monad is lazy enough (the order of
subcomputations does not matter).

However, it is not a monad! The following laws do NOT hold:

  return x >>= k  ===  k x
  m >>= return    ===  m

The reason for this is that `>>=' is the place where the
random seed is distributed. A discussion of this topic can
be found in [1].

In fact, the above trick can also be used for computations
that need to create fresh identifiers. These kind of things
do not need to be single-threaded (and often require
non-single threadedness).

Regards,
Koen.

[1] Koen Claessen and John Hughes, "QuickCheck: A
Lightweight Tool for Random Testing of Haskell Programs",
ICFP, Montreal, Canada, 2000.

--
Koen Claessen         http://www.cs.chalmers.se/~koen     
phone:+46-31-772 5424      mailto:[EMAIL PROTECTED]
-----------------------------------------------------
Chalmers University of Technology, Gothenburg, Sweden


Reply via email to