You might want to attach the “random” tag to your question.
I don't know about PureScript, and documentation seems scarce to the newcomer, but in Haskell circles, it seems to be a rather common complaint: the random number generating function always returning the same value. The usual jokes about random numbers apply.
However, Haskell has an established doctrine regarding random number generation. That does not necessarily involve IO, even though in Haskell the IO monad happens to “host” a random number generator.
In Haskell, you would require:
import System.Random
import Control.Monad.Random
The problem is that a function, given the same arguments, always returns the same result.
The solution is that you need to have the initial state of the random number generator included as a function argument, and the new, updated state returned as part of the result. This is what Haskell function randomR :: RandomGen g => (a, a) -> g -> (a, g) does. The first argument is the output range. If your array has 100 elements indexed between 0 and 99, that would be a 2-tuple: (0,99).
Once you have a function returning a single random value, you can easily build a second one returning an arbitrary number of values, like this for example:
randomRn :: (RandomGen g, Random a) => (a, a) -> Int -> g -> ([a], g)
randomRn range count g0 =
if (count <= 0)
then ([], g0) -- no values and no change
else let (a0, g1) = randomR range g0
(as, gf) = randomRn range (count-1) g1 -- recursive call
in
(a0:as, gf)
You can put your function to use:
main = do
let seed = 4242
g0 = mkStdGen seed -- get a generator
arraySize = 100::Int
range = (0, arraySize-1)
count = 20 -- want "count" random indexes into array
(indexes, gf) = randomRn range count g0
putStrLn $ "Random indexes v1: " ++ show indexes
Program output:
Random indexes v1: [9,56,13,9,38,86,62,18,77,4,66,65,27,33,68,55,94,15,77,45]
Now, depending on taste, style, problem complexity, you might find the explicit presence of the state bothersome, and want to hide it somehow. For this purpose, Haskell uses a variant of the state monad, known as MonadRandom. Using such an approach, you would use code like this to define a monadic action returning a list of random values:
iterateMn :: MonadRandom mr => (Int, Int) -> Int -> mr [Int]
iterateMn range count =
if (count <= 0) then
return [] -- no action required
else
do
v1 <- getRandomR range
vs <- iterateMn range (count-1)
return (v1:vs)
This is essentially the same code as above, except you don't manage the state explicitly. The action is run that way, using function runRand:
let action = iterateMn range count -- monadic action object
(indexes2, gf2) = runRand action g0 -- go generate indexes
More details here: SO_q57890878_r11282404
It seems that the PureScript random number generation facility is built atop the Javascript facility. Depending on how stringent your requirements are, it may or may not be good enough. You might decide to bite the bullet and implement, for example, a PureScript version of random number generator MRG32k3A. Its statistical properties are known to be quite strong, and its state has a very small memory size and is thus neatly adapted to functional programming languages. Apparently there are several Lisp implementations already available.