0

I have previously created this function to generated integers random numbers in a range (m,n).

giveRand :: Random c => c -> c -> c
giveRand m n = unsafePerformIO . getStdRandom $ randomR (m,n)

From this situation I wanted to run it multiple times with the same parameters, so that it would return me a list of randomly generated values in the given range. I tried the replicate function, but it only did copy the result of giveRand. It did not create multiple copies of the function and reevaluate it.

From this problem I wondered if there is a function that allows me to run any function multiple times with the same parameters. I ask this for cases such as this one, that even with the same inputs of range, different values may arise.

So, is there any function in Haskell that enables me to run a function multiple times with the same parameters?

2
  • 2
    You're unlikely to find any standard combinators to do this, as all generic code will be written for the standard assumption that Haskell functions return the same result for the same arguments. The facilities that you've thrown away by using unsafePerformIO are where you would find code that would allow you to turn "generate a random number" into "generate a list of random numbers".
    – Ben
    Commented Aug 25, 2017 at 23:41
  • 6
    I second @Ben's point. (We Bens have got to stick together.) unsafePerformIO is the source of your confusion. I very strongly recommend forgetting that unsafePerformIO exists. It's meant for expert users - the name is meant to scare you off! The situations where you need it are very rare indeed and this is not one of them. Expend your efforts on learning how to work with the IO type instead. It's worth it! Commented Aug 26, 2017 at 0:08

1 Answer 1

8

Forget unsafePerformIO; admit that you are doing something stateful. Here's how:

Control.Monad System.Random> replicateM 3 (randomRIO (5,7))
[6,7,5]

If you must not do IO, you can also make the statefulness explicit with the State monad:

Control.Monad.State System.Random> runState (replicateM 3 (state (randomR (5,7)))) (mkStdGen 0)
([7,7,5],1346387765 2103410263)
1
  • 1
    Or if you don't care about the final generator state you can cleanly use evalState - which is much like fst composed with runState. For example: evalState (replicateM 3 (state (randomR (5,7)))) (mkStdGen 0) [7,7,5] Commented Aug 26, 2017 at 2:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.