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