Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MonadFix instance for Rand monad

I would like to generate infinite stream of numbers with Rand monad from System.Random.MWC.Monad. If only there would be a MonadFix instance for this monad, or instance like this:

instance (PrimMonad m) => MonadFix m where
     ...

then one could write:

runWithSystemRandom (mfix (\ xs -> uniform >>= \x -> return (x:xs)))

There isn't one though.

I was going through MonadFix docs but I don't see an obvious way of implementing this instance.

like image 356
Tener Avatar asked Dec 17 '22 16:12

Tener


1 Answers

You can write a MonadFix instance. However, the code will not generate an infinite stream of distinct random numbers. The argument to mfix is a function that calls uniform exactly once. When the code is run, it will call uniform exactly once, and create an infinite list containing the result.

You can try the equivalent IO code to see what happens:

import System.Random
import Control.Monad.Fix
main = print . take 10 =<< mfix (\xs -> randomIO >>= (\x -> return (x : xs :: [Int])))

It seems that you want to use a stateful random number generator, and you want to run the generator and collect its results lazily. That isn't possible without careful use of unsafePerformIO. Unless you need to produce many random numbers quickly, you can use a pure RNG function such as randomRs instead.

like image 134
Heatsink Avatar answered Jan 08 '23 14:01

Heatsink