It occurs to me that this would be best done by a specific method, like:
interleaveRandom :: (Monad m, RandomGen g) => StateT g m a -> StateT g m a
interleaveRandom (StateT m) = StateT $ \g -> let (gl, gr) = split g in liftM (\p -> (fst p, gr)) $ m gl
It'd act like unsafeInterleaveIO and unsafeInterleaveST, but it'd be safe, and you would know when it actually was splitting.
On 30/07/15 20:38, Zemyla wrote:
> Normally, a monad transformer to provide a random number generator would
> be of the form StateT g, where g is a RandomGen. But I've seen some
> libraries (like QuickCheck) define their RandomT as:
>
> newtype RandomT g m a = RandomT { runRandomT :: g -> m a }
>
> with their monadic bind operation defined as
>
> (RandomT m) >>= f = RandomT $ \g -> let (ga, gb) = split g in m ga >>=
> (\a -> runRandomT (f a) gb)
>
> and return and fail as in ReaderT.
>
> Can someone describe the advantages and disadvantages of doing RandomT
> this way? I mean, if your generator has a subpar split operation (and
> most do), this will obviously exacerbate any problems with it.
tf-random addresses this.
> Does it give any comparable advantages?
It doesn't introduce data dependencies. Let's say you generate a random
binary tree. With the split approach, you can take the right subtree
without evaluating the left one.
Roman
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe