I am trying to generate a sample of random numbers in Haskell
import System.Random
getSample n = take n $ randoms g where
g = newStdGen
but it seems I am not quite using newStdGen the right way. What am I missing?
First off, you probably don't want to use newStdGen. The biggest problem is that you'll get a different seed every time you run your program, so no results will be reproducible. In my opinion, mkStdGen is a better choice as it requires you to give it a seed. This means you will get the same sequence of (pseudo)random numbers every time. If you want a different sequence, just change the seed.
The second problem with newStdGen is that since it's impure, you'll end up in the IO monad which can be a bit inconvenient.
sample :: Int -> IO [Int]
sample n = do
gen <- newStdGen
return $ take n $ randoms gen
You can use do-notation to 'extract' the values and then sum them:
main :: IO ()
main = do
xs <- sample 10
s = sum xs
print s
Or you could 'fmap' the function over the result (but notice that at some point you will probably need to extract the value):
main :: IO ()
main = do
s <- fmap sum $ sample 10
print s
The fmap function is a generalized version of map. Just like map applies a function to the values inside a list, fmap can apply a function to values inside IO.
Another problem with this sample function is that if we call it again, it starts with a fresh seed instead of continuing the previous (pseudo)random sequence. Again, this make reproducing results impossible. In order to fix this problem, we need to pass in the seed and return a new seed. Unfortunately, randoms does not return the next seed for us, so we'll have to write this from scratch using random.
sample :: Int -> StdGen -> ([Int],StdGen)
sample n seed1 = case n of
0 -> ([],seed1)
k -> let (rs,seed2) = sample (k-1) seed1
(r, seed3) = random seed2
in ((r:rs),seed3)
Our main function is now
main :: IO ()
main = do
let seed1 = mkStdGen 123456
(xs,seed2) = sample 10 seed1
s = sum xs
(ys,seed3) = sample 10 seed2
t = sum ys
print s
print t
I know this seems like an awful lot of work just to to use random numbers, but the advantages are worth it. We can generate all of our randomness with a single seed which guarantees that the results can be reproduced.
Of course, this being Haskell, we can take advantage of Monads to get rid of all the manual threading of the seed values. This is a slightly more advanced method, but well worth learning since monads are ubiquitous in Haskell code.
We need these imports:
import System.Random
import Control.Monad
import Control.Applicative
Then we'll create a newtype which represents the action of turning a seed into a value and the next seed.
newtype Rand a = Rand { runRand :: StdGen -> (a,StdGen) }
We need Functor and Applicative instances or GHC will complain, but we can avoid implementing them for this example.
instance Functor Rand
instance Applicative Rand
And now for the Monad instance. This is where the magic happens. The >>= function (called bind) is the one place where we specify how to thread the seed value through the computation.
instance Monad Rand where
return x = Rand ( \seed -> (x,seed) )
ra >>= f = Rand ( \s1 -> let (a,s2) = runRand ra s1
in runRand (f a) s2 )
newRand :: Rand Int
newRand = Rand ( \seed -> random seed )
Now our sample function is extremely simple! We can take advantage of replicateM from Control.Monad which repeats a given action and accumulates the results in a list. All that funny business with the seed values is taken care of behind the scenes
sample :: Int -> Rand [Int]
sample n = replicateM n newRand
main :: IO ()
main = do
let seed1 = mkStdGen 124567
(xs,seed2) = runRand (sample 10) seed1
s = sum xs
print s
We can even stay inside the Rand monad if we need to generate random values multiple times.
main :: IO ()
main = do
let seed1 = mkStdGen 124567
(xs,seed2) = flip runRand seed1 $ do
x <- newRand
bs <- sample 5
cs <- sample 10
return $ x : (bs ++ cs)
s = sum xs
print s
I hope this helps!
Related
When running genRandTupe I continuously get the same random numbers, however when running genrandList with gen as the argument i get a new set of numbers every time. How would I solve this? Why doesn't g = newStdGen generate a new random number?
import System.Random
import System.IO.Unsafe
type RandTupe = (Int,Int)
genRandTupe :: IO RandTupe
genRandTupe = let [a,b] = genrandList g in return (a,b) where g = newStdGen
genrandList gen = let g = unsafePerformIO gen in take 2 (randomRs (1, 20) g)
gen = newStdGen
genRandTupe is a constant applicative form. That means any local variables in its let or where blocks are memoised. Usually quite a convenient feat!
In your case, it means that the list [a,b] is only computed once in your whole program. The way it is computed is actually illegal (don't use unsafePerformIO!), but it doesn't really matter because it only happens once anyway. Wrapping this constant tuple then into IO with return is actually completely superfluent, you could as well have written
genRandTupe' :: RandTupe
genRandTupe' = let [a,b] = genrandList g in (a,b)
where g = newStdGen
OTOH, when you evaluate genrandList gen (not a CAF) in multiple separate places, the result will not necessarily be stored. Instead, that function is calculated anew, using unsafePerformIO to unsafely modify the global state (or maybe not... the compiler is actually free to optimise this away since, you know, genRandList is supposedly a pure function...) and therefore yield a different result each time.
The correct thing, of course, is to stay the heck away from unsafePerformIO. There's actually no need at all to do IO in genRandList, since it already accepts a random generator... just bind that generator out from IO before passing it:
genRandTupe'' :: IO RandTupe
genRandTupe'' = do
g <- newStdGen
let [a,b] = genrandList g
return (a,b)
randListFrom :: RandomGen g => g -> [Int]
randListFrom g = take 2 (randomRs (1, 20) g)
Note that, because the let [a,b] = ... now is in a do block, it's now in the IO monad, decoupled from the CAF closure of genRandTupe''.
I'm writing a program that should be able to simulate many instances of trying the martingale betting system with roulette. I would like main to take an argument giving the number of tests to perform, perform the test that many times, and then print the number of wins divided by the total number of tests. My problem is that instead of ending up with a list of Bool that I could filter over to count successes, I have a list of IO Bool and I don't understand how I can filter over that.
Here's the source code:
-- file: Martingale.hs
-- a program to simulate the martingale doubling system
import System.Random (randomR, newStdGen, StdGen)
import System.Environment (getArgs)
red = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]
martingale :: IO StdGen -> IO Bool
martingale ioGen = do
gen <- ioGen
return $ martingale' 1 0 gen
martingale' :: Real a => a -> a -> StdGen -> Bool
martingale' bet acc gen
| acc >= 5 = True
| acc <= -100 = False
| otherwise = do
let (randNumber, newGen) = randomR (0,37) gen :: (Int, StdGen)
if randNumber `elem` red
then martingale' 1 (acc + bet) newGen
else martingale' (bet * 2) (acc - bet) newGen
main :: IO ()
main = do
args <- getArgs
let iters = read $ head args
gens = replicate iters newStdGen
results = map martingale gens
--results = map (<-) results
print "THIS IS A STUB"
Like I have in my comments, I basically want to map (<-) over my list of IO Bool, but as I understand it, (<-) isn't actually a function but a keyword. Any help would be greatly appreciated.
map martingale gens will give you something of type [IO Bool]. You can then use sequence to unpack it:
sequence :: Monad m => [m a] -> m [a]
A more natural alternative is to use mapM directly:
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
i.e. you can write
results <- mapM martingale gens
Note - even after doing it this way, your code feels a bit unnatural. I can see some advantages to the structure, in particular because martingale' is a pure function. However having something of type IO StdGen -> IO Bool seems a bit odd.
I can see a couple of ways to improve it:
make martingale' return an IO type itself and push the newStdGen call all the way down into it
make gens use replicateM rather than replicate
You may want to head over to http://codereview.stackexchange.com for more comprehensive feedback.
I'm currently trying to encrypt a message (String) with the help of a random generated number in Haskell. The idea is to get the message, generate a random String of numbers with the same length (or more and then to take the length I need).
Then i want to perform some actions based on the ASCII representation and then return the encrypted String.
Unfortunately I'm not very versed with monads in Haskell, so it might be a very simple problem to solve, which I can't comprehend yet.
generateMyKey string = newStdGen >>= \x -> print $ concatMap show $ map abs $ rs x
where rs x = randomlist (length string) x
randomlist :: Int -> StdGen -> [Int]
randomlist n = take n . unfoldr (Just . random)
So the problem is I get an IO() out of getMyKey, but I want to have a String, or atleast a IO(String) to perform the encrypting mechanism.
Right now I'm getting a big list of positive (hence the abs + map) random numbers, but I can't access them.
There are two basic ways to go about this (and one more complicated but easier). If you're just using System.Random, you can generate random numbers in two ways, either by accepting a StdGen and staying pure, or using the OS's random generator and staying in IO. At some point, you'll have to make a call to the OS's random functionality to get a seed or value, but this can happen in main far away from your actual code.
To keep your functions pure, you'll need to pass around a StdGen and use the functions
random :: Random a => StdGen -> (a, StdGen)
randoms :: Random a => StdGen -> [a]
(Note: I've substituted RandomGen g => g for StdGen, there's no need to write a custom RandomGen instance for your case)
You can then write your function generateMyKey as
randomList :: Int -> StdGen -> [Int]
randomList n = take n . randoms
generateMyKey :: String -> StdGen -> String
generateMyKey text g
= concatMap show
$ map abs
$ randomList (length text) g
And this entirely avoids having to live in IO. Be wary, though, if you re-use the same g, you'll generate the same random list each time. We can avoid this by using IO and its related functions
randomList :: Int -> IO [Int]
randomList 0 = return []
randomList n = do
first <- randomIO
rest <- randomList (n - 1) -- Recursively generate the rest
return $ first : rest
generateMyKey :: String -> IO String
generateMyKey text = do
key <- randomList (length text)
return $ concatMap show $ map abs $ key
This will come with a performance hit, and now we've lost the ability to generate the same key repeatedly, making it difficult to test our functions reliably! How can we reconcile these two approaches?
Enter the package MonadRandom. This package provides a monad (and monad transformer, but you don't need to worry about that right now) that lets you abstract away how you generate random numbers so that you can choose how you want to run your code in different circumstances. If you want IO, you can use IO. If you want to supply a seed, you can supply a seed. It's very handy. You can install it with cabal install MonadRandom and use it as
import Control.Monad.Random
randomList :: Int -> Rand StdGen [Int]
randomList n = fmap (take n) getRandoms
generateMyKey :: String -> Rand StdGen String
generateMyKey text = do
key <- randomList (length text)
return $ concatMap show $ map abs $ key
Our generateMyKey code is even the same as the IO version other than the type signature!
Now to run it.
main :: IO ()
main = do
-- Entirely impure, have it automatically grab a StdGen from IO for us
ioVersion <- evalRandIO $ generateMyKey "password"
-- Make a StdGen that stays the same every time we run the program, useful for testing
let pureStdGen = mkStdGen 12345
pureVersion = evalRand (generateMyKey "password") pureStdGen
-- Get a StdGen from the system, but still evaluate it purely
ioStdGen <- getStdGen
let pureVersion2 = evalRand (generateMyKey "password") ioStdGen
-- Print out all three versions
putStrLn ioVersion
putStrLn pureVersion
putStrLn pureVersion2
There are a number of solutions to this problem, but at first glance it might seem that you need to have your entire program operate in the IO monad, but you don't! The entry (/exit) point of your program is the only place that needs to see IO -- you can factor out any transformations on your random list into pure functions, i.e:
import Data.List
import System.Random
generateMyKey :: String -> IO String
generateMyKey string = do
x <- newStdGen
let rs = randomlist (length string)
return $ concatMap show $ map abs $ rs x
randomlist :: Int -> StdGen -> [Int]
randomlist n = take n . unfoldr (Just . random)
change :: String -> String
change = reverse -- for example
main :: IO ()
main = do
key <- generateMyKey "what"
putStrLn $ change key
generateMyKey is identical to what you had before, except that it's written in do notation now and is returning the string instead of just printing it. This allows us to "pull out" a random key from inside the IO monad and transform it with regular pure functions, like change, for example. This allows you to reason about the pure functions as normal, while still pulling in your values from IO.
This question already has answers here:
Random number in Haskell [duplicate]
(5 answers)
Closed 8 years ago.
I am in the process of learning Haskell and to learn I want to generate a random Int type. I am confused because the following code works. Basically, I want an Int not an IO Int.
In ghci this works:
Prelude> import System.Random
Prelude System.Random> foo <- getStdRandom (randomR (1,1000000))
Prelude System.Random> fromIntegral foo :: Int
734077
Prelude System.Random> let bar = fromIntegral foo :: Int
Prelude System.Random> bar
734077
Prelude System.Random> :t bar
bar :: Int
So when I try to wrap this up with do it fails and I don't understand why.
randomInt = do
tmp <- getStdRandom (randomR (1,1000000))
fromIntegral tmp :: Int
The compiler produces the following:
Couldn't match expected type `IO b0' with actual type `Int'
In a stmt of a 'do' block: fromIntegral tmp :: Int
In the expression:
do { tmp <- getStdRandom (randomR (1, 1000000));
fromIntegral tmp :: Int }
In an equation for `randomInt':
randomInt
= do { tmp <- getStdRandom (randomR (1, 1000000));
fromIntegral tmp :: Int }
Failed, modules loaded: none.
I am new to Haskell, so if there is a better way to generate a random Int without do that would be preferred.
So my question is, why does my function not work and is there a better way to get a random Int.
The simple answer is that you can't generate random numbers without invoking some amount of IO. Whenever you get the standard generator, you have to interact with the host operating system and it makes a new seed. Because of this, there is non-determinism with any function that generates random numbers (the function returns different values for the same inputs). It would be like wanting to be able to get input from STDIN from the user without it being in the IO monad.
Instead, you have a few options. You can write all your code that depends on a randomly generated value as pure functions and only perform the IO to get the standard generator in main or some similar function, or you can use the MonadRandom package that gives you a pre-built monad for managing random values. Since most every pure function in System.Random takes a generator and returns a tuple containing the random value and a new generator, the Rand monad abstracts this pattern out so that you don't have to worry about it. You can end up writing code like
import Control.Monad.Random hiding (Random)
type Random a = Rand StdGen a
rollDie :: Int -> Random Int
rollDie n = getRandomR (1, n)
d6 :: Random Int
d6 = rollDie 6
d20 :: Random Int
d20 = rollDie 20
magicMissile :: Random (Maybe Int)
magicMissile = do
roll <- d20
if roll > 15
then do
damage1 <- d6
damage2 <- d6
return $ Just (damage1 + damage2)
else return Nothing
main :: IO ()
main = do
putStrLn "I'm going to cast Magic Missile!"
result <- evalRandIO magicMissile
case result of
Nothing -> putStrLn "Spell fizzled"
Just d -> putStrLn $ "You did " ++ show d ++ " damage!"
There's also an accompanying monad transformer, but I'd hold off on that until you have a good grasp on monads themselves. Compare this code to using System.Random:
rollDie :: Int -> StdGen -> (Int, StdGen)
rollDie n g = randomR (1, n) g
d6 :: StdGen -> (Int, StdGen)
d6 = rollDie 6
d20 :: StdGen -> (Int, StdGen)
d20 = rollDie 20
magicMissile :: StdGen -> (Maybe Int, StdGen)
magicMissile g =
let (roll, g1) = d20 g
(damage1, g2) = d6 g1
(damage2, g3) = d6 g2
in if roll > 15
then (Just $ damage1 + damage2, g3)
else Nothing
main :: IO ()
main = do
putStrLn "I'm going to case Magic Missile!"
g <- getStdGen
let (result, g1) = magicMissile g
case result of
Nothing -> putStrLn "Spell fizzled"
Just d -> putStrLn $ "You did " ++ show d ++ " damage!"
Here we have to manually have to manage the state of the generator and we don't get the handy do-notation that makes our order of execution more clear (laziness helps in the second case, but it makes it more confusing). Manually managing this state is boring, tedious, and error prone. The Rand monad makes everything much easier, more clear, and reduces the chance for bugs. This is usually the preferred way to do random number generation in Haskell.
It is worth mentioning that you can actually "unwrap" an IO a value to just an a value, but you should not use this unless you are 100% sure you know what you're doing. There is a function called unsafePerformIO, and as the name suggests it is not safe to use. It exists in Haskell mainly for when you are interfacing with the FFI, such as with a C DLL. Any foreign function is presumed to perform IO by default, but if you know with absolute certainty that the function you're calling has no side effects, then it's safe to use unsafePerformIO. Any other time is just a bad idea, it can lead to some really strange behaviors in your code that are virtually impossible to track down.
I think the above is slightly misleading. If you use the state monad then you can do something like this:
acceptOrRejects :: Int -> Int -> [Double]
acceptOrRejects seed nIters =
evalState (replicateM nIters (sample stdUniform))
(pureMT $ fromIntegral seed)
See here for an extended example of usage:Markov Chain Monte Carlo
I've been messing with Haskell few days and stumbled into a problem.
I need a method that returns a random list of integers ( Rand [[Int]] ).
So, I defined a type: type Rand a = StdGen -> (a, StdGen).
I was able to produce Rand IO Integer and Rand [IO Integer] ( (returnR lst) :: StdGen -> ([IO Integer], StdGen) ) somehow. Any tips how to produce Rand [[Int]]?
How to avoid the IO depends on why it's being introduced in the first place. While pseudo-random number generators are inherently state-oriented, there's no reason IO needs to be involved.
I'm going to take a guess and say that you're using newStdGen or getStdGen to get your initial PRNG. If that's the case, then there's no way to completely escape IO. You could instead seed the PRNG directly with mkStdGen, keeping in mind that the same seed will result in the same "random" number sequence.
More likely, what you want to do is get a PRNG inside IO, then pass that as an argument to a pure function. The entire thing will still be wrapped in IO at the end, of course, but the intermediate computations won't need it. Here's a quick example to give you the idea:
import System.Random
type Rand a = StdGen -> (a, StdGen)
getPRNG = do
rng <- newStdGen
let x = usePRNG rng
print x
usePRNG :: StdGen -> [[Int]]
usePRNG rng = let (x, rng') = randomInts 5 rng
(y, _) = randomInts 10 rng'
in [x, y]
randomInts :: Int -> Rand [Int]
randomInts 0 rng = ([], rng)
randomInts n rng = let (x, rng') = next rng
(xs, rng'') = randomInts (n - 1) rng'
in (x:xs, rng'')
You might notice that the code using the PRNG gets pretty ugly due to passing the current value back and forth constantly. It's also potentially error prone, since it'd be easy to accidentally reuse an old value. As mentioned above, using the same PRNG value will give the same sequence of numbers, which is usually not what you want. Both problems are a perfect example of where it makes sense to use a State monad--which is getting off topic here, but you may want to look into it next.
You are recreating MonadRandom on Hackage. If this is more than just an experiment to see if you can do it, you might want to use that library instead.
If you want to get an infinite list of Integers you're going to run into problems as you won't ever get a StdGen value back out. What you want to do here is split the StdGen first, pass one half out again and 'use up' the other half to generate an infinite list of integers. Something like this:
infiniteRandomInts :: Rand [Int]
infiniteRandomInts g = (ints, g2) where
(g1,g2) = split g
ints = randoms g1
However, if you then repeat this approach to get an infinite matrix of Integers (which you seem to want, by using Rand [[Int]]), you might run into problems of a statistical nature: I don't know how well StdGen deals with repeated splitting. Maybe another implementation of RandomGen might be better, or you could try to use some sort of diagonal walk to turn a [Int] into a [[Int]].
Using monadic notation, you should be able to write something like
randomList gen = do
randomLength <- yourRandomInteger
loop gen (randomLength + 1)
where
loop gen 1 = gen
loop gen n = do { x <- gen; xs <- loop gen (n - 1); return (x:xs) }
And with this
randomInts :: Rand [Int]
randomInts = randomList yourRandomInteger
randomLists :: Rand [[Int]]
randomLists = randomList randomInts
Concerning the monadic computations itself, take a look at this article. Note that random generators are pure, you shouldn't need any IO just for this purpose.