From the Haskell wikibook we have:
import Control.Monad
import Control.Monad.Trans.State
import System.Random
type GeneratorState = State StdGen
rollDie :: GeneratorState Int
rollDie = do
generator <- get
let (value, newGenerator) = randomR (1,6) generator
put newGenerator
return value
If we execute:
evalState rollDie (mkStdGen 0)
then we get a return type of Int.
This much I understand, but I am wondering if it is possible to wire into this logic the use of the system generator accessed by the function getStdGen. The getStdGen function operates in the IO monad, and my question is (surely this must be the MOST often asked Haskell question) how can you get the generator out of the IO context to use in the non IO monad code above?
Apologies for the newbie question. I am aware that one should not use unsafePerformIO, but otherwise perplexed.
The core of the matter is that it's impossible to produce random numbers out of thin air. You either seed a generator with some input (that's what you do with mkStdGen 0), or you can take the system one with getStdGen.
The problem with mkStdGen 0 is that it's a constant, so your stream of random numbers will show its pseudo-randomness very clearly by being a constant too.
The problem with getStdGen is that it's in the IO monad.
You can't get the generator out of IO to use in a pure computation, that's the whole point of making IO a monad. But within IO, you can bind it using the normal do-notation:
main = do
gen <- getStrGen
print $ evalState rollDie gen
Of course, it'll only produce unique results once.
I heartily concur with the comment recommending MonadRandom. I've been using it for my random-based computations since I found out about it, and haven't looked back.
Related
I need to create random data in Haskell.
I want my code to be:
a) reproducible from a seed
b) the threading of generators to be implicit
I understand Monads generally and the way that Random Generators work.
My approach is to thread the generator through the code so I can reproduce the random numbers but want to hide the threading of the generators in a Monad.
I'm thinking that the State Monad is a good approach.
Here's some simple code:
type Gen a = State StdGen a
roll :: Gen Int
roll = state $ randomR (1, 6)
roll2 :: Gen Int
roll2 = (+) <$> roll <*> roll
test :: Int -> IO ()
test seed = do
let gen = mkStdGen seed
print (evalState roll gen)
print (evalState roll gen)
print (evalState roll2 gen)
print (evalState roll2 gen)
I'm trying to use State so that I can push the threading of the generator into the State Monad but the results of roll are the same and results of roll2 are the same. I can see that this is because I'm passing gen into the functions multiple times so of course it would produce the same output. So that makes me think I need to get a new generator from each function. But then I'm back to having to thread the generator through the code which is what I'm trying to avoid by using State. I feel like I'm missing a trick!
I explored MonadRandom too and that did push the threading away from my code but I couldn't see how to make that approach be reproducible.
I've hunted a lot and tried many things but seem to always either be able to hide the generators OR make the code reproducible but not both.
I'm keen to use a Monad more specific than IO.
I'm also going to build a series of more complex functions which will generate random lists of numbers so I need to have a simple way to make these random functions rely on each other. I managed that with MonadRandom but again I couldn't see how that could be reproducible.
Any help appreciated.
If you needn't interleave IO with randomness, as here, then the answer is just to lump your State actions together into one with the Monad operations (they're the thing passing the state around for you!).
test :: Int -> IO ()
test seed = do
print a
print b
print c
print d
where
(a,b,c,d) = flip evalState (mkStdGen seed) $ do
a <- roll
b <- roll
c <- roll2
d <- roll2
return (a,b,c,d)
If you will need to interleave IO and randomness, then you will want to look into StateT StdGen IO as your monad instead of using State StdGen and IO separately. That might look like this, say:
roll :: MonadState StdGen m => m Int
roll = state (randomR (1,6))
roll2 :: MonadState StdGen m => m Int
roll2 = (+) <$> roll <*> roll
test :: (MonadState StdGen m, MonadIO m) => m ()
test = do
roll >>= liftIO . print
roll >>= liftIO . print
roll2 >>= liftIO . print
roll2 >>= liftIO . print
(You could then use e.g. evalStateT test (mkStdGen seed) to turn this back into an IO () action, or embed it into a larger computation if there were further random things you needed to generate and do IO about.)
MonadRandom does little more than package up StateT StdGen in a way that lets you still use non-seed state, so I encourage you to reconsider using it. evalRand and evalRandT from Control.Monad.Random.Lazy (or .Strict) shouldy give you the repeatability you need; if they don't, you should open a fresh question with the full details of what you tried and how it went wrong.
Normally, it's pretty much the whole point of a random generator that you don't always get the same result. And that's the reason why you use a state monad: to pass on the updated generator, so that the next random event will actually be different.
If you want always the same value, then there's not really any reason to use special random tooling at all – just generate one value once (or two values), then pass it on whereever needed, like you would pass on another variable.
test :: IO ()
test = do
[dice0, dice1] <- replicateM 2 $ randomRIO (1,6)
print dice0
print dice0
print $ dice0+dice1
print $ dice0+dice1
In Haskell, I'd like to generate a random list of Ints and use it throughout my program. My current solution causes the array to be created randomly each time I access/use it.
How can I overcome this problem?
Here is a simple example (#luqui mentioned) you should be able to generalize to your need:
module Main where
import Control.Monad (replicateM)
import System.Random (randomRIO)
main :: IO ()
main = do
randomList <- randomInts 10 (1,6)
print randomList
let s = myFunUsingRandomList randomList
print s
myFunUsingRandomList :: [Int] -> Int
myFunUsingRandomList list = sum list
randomInts :: Int -> (Int,Int) -> IO [Int]
randomInts len bounds = replicateM len $ randomRIO bounds
remarks
randomInts is an IO-action that will produce you your random list of integers, you see it's use in the very first line of mains do-block. Once it is used there the list will stay the same.
myFunUsingRandomList is a very simple example (just summing it) of using such a list in a pure fashion - indeed it just expects a list of integers and I just happen to call it with the random list from main
Follow this example. Then, pass rs from main to whatever function needs it.
You can't have a global variable for this without using something like unsafePerformIO, which, as the name indicates, should not be used. The reason is that picking random numbers is an inherently non-deterministic operation, dependent on the outside IO state.
I want to handle/store random generator(Gen (ST {..}) outside of ST monad, but I couldn't find how to do.
Background
I'm under working for some simulation which uses random heavily.
With profiling, I knew that make random numbers takes more than 50% of process time.
To make random number, I use mwc-random and SFMT.
Because of speed issue, I mainly use SFMT.
However, comeparing with SFMT, mwc-random have richer interfaces that I need(like normal, bernoulli, ..).
After benchmark and read codes, I understand that mwc-random is not too slow than SFMT when it is used on ST monad.
(SFMT on IO < MWC on ST << MWC on IO < SFMT on ST)
So, I want to make and handle MWC random generator on ST monad.
However, I cannot take this generator out from ST monad as same as other ST things(e.g. STRef).
Problem
Is there any way to handle/store this random generator outside of ST monad safely?
I tried to study from many packages/codes with STRef or something others, but I couldn't figure it out.
Example
I use random generator in the simulation like this way.
import qualified System.Random.MWC as MWC
import GHC.Prim
import Control.Monad
data World = World { randomGen :: MWC.Gen RealWorld }
initWorld = do gen <- MWC.create
return $ World gen
something gen = do num <- MWC.uniformR (1,100) gen :: IO Int
print num
main = do world <- initWorld
replicateM_ 100 $ something (randomGen world)
But, this code does not works.
import qualified System.Random.MWC as MWC
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.ST
data World s = World { randomGen :: MWC.Gen (PrimState (ST s))}
initWorld :: ST s (World s)
initWorld = do gen <- MWC.create
return $ World gen
something gen = do
let num :: Int
num = runST $ do num <- MWC.uniformR (1,100) gen
return num
print num
main = do let world = runST initWorld
replicateM_ 100 $ something (randomGen world)
I want rewrite this code to work with something.
Do I need to define/rewrite data structure or do something other?
Is there more smart way?
Points:
I need to handle a random generator (like Gen (PrimState (ST s))) to reproduce results.
So, I do not want to produce ad-hoc random generator.
I do not wants to save/restore seed. It has too big overhead.
(save/restore seed takes x12~15 time more than generate one random number)
It is slower than using on IO monad, so I do not need to do on ST monad.
I do not want to use unsafe* functions.
You shouldn't try to manipulate the generator outside of the ST monad. Because of the type of runST, trying to use things which live "inside" the state thread "outside" of it is non-nonsensical. Imagine you had a function of the following type (which is the function you are trying to write):
something :: MWC.Gen s -> Int
something gen = runST ...
In order to generate random numbers, some stateful computations must be done with the data inside of the Gen. At which point will those computations be done? How many times will they be done, if at all? Most importantly - how can something be generating random numbers - it is a pure function, after all, so it must return the same value for the same input.
Instead, you should thread the state along, and call runST at the end:
something :: MWC.Gen s -> ST s Int
something = MWC.uniformR (1,100)
main = mapM_ print $ runST $ do
w0 <- initWorld
replicateM 100 (something $ randomGen w0)
I want to provide a function that replaces each occurrence of # in a string with a different random number. In a non-pure language, it's trivial. However, how should it be designed in a pure language? I don't want to use unsafePerformIO, as it rather looks like a hack and not a proper design.
Should this function require a random generator as one of its parameters? And if so, would that generator have to be passed through the whole stack of invocations? Are there other possible approaches? Should I use the State monad, here? I would appreciate a toy example demonstrating a viable approach...
You would, in fact, use a variant of the state monad to pass the random generator around behind the scenes. The Rand type in Control.Monad.Random helps with this. The API is a bit confusing, but more because it's polymorphic over the type of random generator you use than because it has to be functional. This extra bit of scaffolding is useful, however, because you can easily reuse your existing code with different random generators which lets you test different algorithms as well as explicitly controlling whether the generator is deterministic (good for testing) or seeded with outside data (in IO).
Here's a simple example of Rand in action. The RandomGen g => in the type signature tells us that we can use any type of random generator for it. We have to explicitly annotate n as an Int because otherwise GHC only knows that it has to be some numeric type that can be generated and turned into a string, which can be one of multiple possible options (like Double).
randomReplace :: RandomGen g => String -> Rand g String
randomReplace = foldM go ""
where go str '#' = do
n :: Int <- getRandomR (0, 10)
return (str ++ show n)
go str chr = return $ str ++ [chr]
To run this, we need to get a random generator from somewhere and pass it into evalRand. The easiest way to do this is to get the global system generator which we can do in IO:
main :: IO ()
main = do gen <- getStdGen
print $ evalRand (randomReplace "ab#c#") gen
This is such a common pattern that the library provides an evalRandIO function which does it for you:
main :: IO ()
main = do res <- evalRandIO $ randomReplace "ab#c#"
print res
In the end, the code is a bit more explicit about having a random generator and passing it around, but it's still reasonably easy to follow. For more involved code, you could also use RandT, which allows you to extend other monads (like IO) with the ability to generate random values, letting you relegate all the plumbing and setup to one part of your code.
It's just a monadic mapping
import Control.Applicative
import Control.Monad.Random
import Data.Char
randomReplace :: RandomGen g => String -> Rand g String
randomReplace = mapM f where
f '#' = intToDigit <$> getRandomR (0, 10)
f c = return c
main = evalRandIO (randomReplace "#abc#def#") >>= print
I went through some tutorials on the State monad and I think I got the idea.
For example, as in this nice tutorial:
import Data.Word
type LCGState = Word32
lcg :: LCGState -> (Integer, LCGState)
lcg s0 = (output, s1)
where s1 = 1103515245 * s0 + 12345
output = fromIntegral s1 * 2^16 `div` 2^32
getRandom :: State LCGState Integer
getRandom = get >>= \s0 -> let (x,s1) = lcg s0
in put s1 >> return x
OK, so I can use getRandom:
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 1
(16838,1103527590)
But I still need to pass the seed to the PRNG every time I call it. I know that the
PRNG available in Haskell implementations does not need that:
Prelude> :module Random
Prelude Random> randomRIO (1,6 :: Int)
(...) -- GHC prints some stuff here
6
Prelude Random> randomRIO (1,6 :: Int)
1
So I probably misunderstood the State monad, because what I could see in most tutorials
doesn't seem to be "persistent" state, but just a convenient way to thread state.
So... How can I have state that is automatically initialized (possible from some
function that uses time and other not-very-predictable data), like the Random module
does?
Thanks a lot!
randomRIO uses the IO monad. This seems to work nicely in the interpreter because the interpreter also works in the IO monad. That's what you are seeing in your example; you can't actually do that at the top-level in code -- you would have to put it in a do-expression like all monads anyway.
In general code you should avoid the IO monad, because once your code uses the IO monad, it is tied to external state forever -- you can't get out of it (i.e. if you have code that uses the IO monad, any code that calls it also has to use the IO monad; there is no safe way to "get out" of it). So the IO monad should only be used for things like accessing the external environment, things where it is absolutely required.
For things like local self-contained state, you should not use the IO monad. You can use the State monad as you have mentioned, or you can use the ST monad. The ST monad contains a lot of the same features as the IO monad; i.e. there is STRef mutable cells, analogous to IORef. And the nice thing about ST compared to IO is that when you are done, you can call runST on an ST monad to get the result of the computation out of the monad, which you can't do with IO.
As for "hiding" the state, that just comes as part of the syntax of do-expressions in Haskell for monads. If you think you need to explicitly pass the state, then you are not using the monad syntax correctly.
Here is code that uses IORef in the IO Monad:
import Data.IORef
foo :: IO Int -- this is stuck in the IO monad forever
foo = do x <- newIORef 1
modifyIORef x (+ 2)
readIORef x
-- foo is an IO computation that returns 3
Here is code that uses the ST monad:
import Control.Monad.ST
import Data.STRef
bar :: Int
bar = runST (do x <- newSTRef 1
modifySTRef x (+ 2)
readSTRef x)
-- bar == 3
The simplicity of the code is essentially the same; except that in the latter case we can get the value out of the monad, and in the former we can't without putting it inside another IO computation.
secretStateValue :: IORef SomeType
secretStateValue = unsafePerformIO $ newIORef initialState
{-# NOINLINE secretStateValue #-}
Now access your secretStateValue with normal readIORef and writeIORef, in the IO monad.
So I probably misunderstood the State monad, because what I could see in most tutorials doesn't seem to be "persistent" state, but just a convenient way to thread state.
The state monad is precisely about threading state through some scope.
If you want top level state, that's outside the language (and you'll have to use a global mutable variable). Note how this will likely complicated thread safety of your code -- how is that state initialized? and when? And by which thread?