I'm trying to extend the code in this post (accepted answer) to allow me to be able to call randomGen2 to get a random number, based on the function randomGen which takes a seed as an argument. But everytime I call randomGen2, despite returning an Int, I get an error about not been able to print Random (when infact I am only trying to print Int).
<interactive>:3:1:
No instance for (Show (Random Int))
arising from a use of `print'
Possible fix: add an instance declaration for (Show (Random Int))
In a stmt of an interactive GHCi command: print it
Here's the code:
import Control.Monad.State
type Seed = Int
randomGen :: Seed -> (Int, Seed)
randomGen seed = (seed,seed+1)
type Random a = State Seed a
randomGen2 :: Random Int
randomGen2 = do
seed <- get
let (x,seed') = randomGen seed
put seed'
return x
any ideas?
Update - expected behaviour
I'm hoping to be able to do something this from an interpreter (e.g. GHCI) -
> getRandomInit 1
> -- some other stuff, e.g. 2 + 3
> getRandom
i.e. I can set up my getRandom function with a seed, which then stores the seed using put, then this function returns and exits. I then do some other stuff, then call getRandom again, and the seed is retrieved from the Monad where it was stored.
randomGen2 returns a Random Int which is a State Seed Int so you'll need to use runState to get a result by providing a seed value e.g.
runState randomGen2 1
If you want to keep repeating the application of randomGen2 you can create a function like:
genRandoms :: Seed -> [Int]
genRandoms s = let (v, s') = runState randomGen2 s in v : genRandoms s'
or you could use sequence:
genRandoms :: Seed -> [Int]
genRandoms s = fst $ runState (sequence (repeat randomGen2)) s
Related
So in a project of my I have a constant function that returns an array :
import System.Random
giveList :: [Int]
giveList = [8,9,4,5,2]
and I would like to randomly select an element from that list like this:
seed::Int
seed = 40
generator = mkStdGen seed
giveRandomElement :: Int
giveRandomElement = giveList !! rand where
n = length tetrominoes
(rand,generator) = randomR (0,(n-1)) generator
However, this does not compile because of the generator, I would like to keep the generator as a global variable so I don't have to keep giving it to functions.
I also don't want to deal with IO wrappers, so in what way can I do this ?
Thx for the help :-)
A working code example
import System.Random
seed::Int
seed = 40
giveList :: [Int]
giveList = [8,9,4,5,2]
generator = mkStdGen seed
giveRandomElement :: Int
giveRandomElement = giveList !! rand where
n = length giveList
(rand, _) = randomR (0,(n-1)) generator
But that probably doesn't do, what you want.
giveRandomElement will always yield the same result. It is a pure function without any inputs, so what should it do? It can only be constant.
You either need to use IO or you need to thread your generator through your code and keep track of it somewhere.
The compiler error you got:
test.hs:14:23: error:
• Ambiguous type variable ‘g0’ arising from a use of ‘randomR’
prevents the constraint ‘(RandomGen g0)’ from being solved.
Relevant bindings include generator :: g0 (bound at test.hs:14:10)
Probable fix: use a type annotation to specify what ‘g0’ should be.
These potential instance exist:
instance RandomGen StdGen -- Defined in ‘System.Random’
• In the expression: randomR (0, (n - 1)) generator
In a pattern binding:
(rand, generator) = randomR (0, (n - 1)) generator
In an equation for ‘giveRandomElement’:
giveRandomElement
= giveList !! rand
where
n = length giveList
(rand, generator) = randomR (0, (n - 1)) generator
|
14 | (rand, generator) = randomR (0,(n-1)) generator
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
was because you defined the symbol generator in giveRandomElement in terms
of it self and so the compiler couldn't deduce its type. (The top level declaration generator wasn't used in that case, because (rand, generator) = already shadowed the symbol after the equal sign.
I would like to keep the generator as a global variable so I don't have to keep giving it to functions. I also don't want to deal with IO wrappers, so in what way can I do this ?
Sorry, a function giveRandomElement :: Int that returns a different random number every time you call it isn't referentially transparent, so Haskell's purity does not allow you to do what you'd like.
I think working with random values is a great opportunity to learn about monads. MonadRandom has a very flexible interface for writing functions whose results are random:
die :: (MonadRandom m) => m Int
die = getRandomR (1, 6)
rollDice :: (MonadRandom m) => m (Int, Int)
rollDice = do
x <- die
y <- die
return (x, y)
-- Your example
giveRandomElement :: (MonadRandom m) => m Int
giveRandomElement = do
let n = length tetrominoes
i <- getRandomR (0, n-1)
return (giveList !! i)
The implementations of this monad will thread the randomness state through your random functions for you. There's even an instance MonadRandom IO, which lets you write
main :: IO ()
main = do
x <- giveRandomElement
print x
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!
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 have been given this snippet of code and am supposed to explain it's non termination and propose a possible fix.
randomW = do randomvalues <- sequence (repeat (randomIO :: IO Float))
print (take 10 randomvalues)
Condition for the fix is to keep generating an infinite list so we may use the take function.
I think the problem stems from the not-so-lazy nature of the sequence function, which tries to reach the end of the list generated by repeat (randomIO :: IO Float), leading to non termination.
I'm also not sure about whether the repeat function is possible on randomIO.
test = do random <- repeat (randomIO :: IO Float)
print random
Which yields a type error. Print can't seem to be able to handle an IO Float, which seems to suggest that you can use repeat on type IO Float.
So:
repeat :: a -> [a]
randomIO :: Random a => IO a
sequence :: Monad m => [m a] -> m [a]
=>
repeat (randomIO :: IO Float) :: [IO Float]
So when you do:
random <- repeat (randomIO :: IO Float)
You're actually exploiting the list monad here, so random has type IO Float. Since you're in the list monad, your last statement needs to have type [a], but it has type IO () since it's a call to print, hence the type error.
The whole point of sequence is to transform this [IO a] into an IO [a] that you can perform to obtain a list of random values, and hopefully print this list. Now, when you perform an IO like this, it needs to be performed all at once, unless using unsafeInterleaveIO, which is not recommended in this case. So it tries to get that infinite list... and hangs (it might stack overflow at some point, I'm not sure).
To get an infinite list of random values, you don't need all this, just to obtain a random seed, and compute random values purely from the seed.
You should be able to construct an infinite list of random values using these functions:
randomIO :: Random a => IO a -- to provide an IO Int
mkStdGen :: Int -> StdGen -- to obtain a random generator from that Int
randoms :: RandomGen g => g -> [a] -- to generate the infinite list
Notice that the last two functions are pure. Reading this thread might give you some more ideas.
EDIT:
Example of how you should use mkStdGen:
randomList :: Random a => IO [a]
randomList = do seed <- randomIO
let gen = mkStdGen seed
return (randoms gen)
I can't test it right now but this should work. You probably want to adapt this to your use case though.
For your other question:
map :: (a -> b) -> [a] -> [b]
print :: Show a => a -> IO ()
=>
map print :: Show a => [a] -> [IO ()]
This probably isn't what you want, right?
If you just want to print a list, no need for map, print can handle lists.
The reason why your first code does not work, is that you're trying to sequence an infinite number of IO actions. Since this uses strict IO, the program is not allowed to continue before all the actions have been performed, which will take forever.
A simple solution is to take the number of actions you need before sequencing them, for example:
randomW = do values <- sequence (take 10 $ repeat (randomIO :: IO Float))
print values
This can be written more succinctly using replicateM from Control.Monad:
randomW = do values <- replicateM 10 (randomIO :: IO Float)
print values
Or, you can use randoms to make an infinite list of random numbers based on a single random seed (similar to Ptival's answer):
randomW = do gen <- newStdGen
let randomValues = randoms gen :: [Float]
print (take 10 randomValues)
Here, we only use a single IO action and the infinite list is generated lazily based on that, so there is no infinite number of side effects to run.