Reputation: 33901
I've had a look through https://hackage.haskell.org/package/random-1.1/docs/System-Random.html however I can't see how to use a custom "list" for example an alphanumeric list of ['a'..'z'] ++ ['0' .. '9']
?
I suppose as a workaround I could instead map a random set of numbers instead.
Upvotes: 2
Views: 409
Reputation: 4733
Assuming you can do with sampling with replacement a fixed number of characters from a fixed string, perhaps it is helpful to repackage a bit the code from SO_q57836652.
Side note: if you don't want replacement, you will have to look at that shuffle thing pointed to by @Redu in the comments, or maybe also here.
You can package your specification into a random “action”, something that's handy and chainable, like this:
import System.Random
import Control.Monad.Random
---- import qualified System.Random.Shuffle as SHF -- only for no replacement
-- return many random numbers from some given range:
mkRandSeqMr :: (MonadRandom mr, Random tv) => (tv,tv) -> Int -> mr [tv]
mkRandSeqMr range count =
let act1 = getRandomR range in sequence (replicate count act1)
makeRandomString :: (MonadRandom mr) => String -> Int -> mr String
makeRandomString bigString count =
let range = (0, (length bigString) - 1)
in do
-- "do construct" within the Random monad - not the IO monad
nums <- mkRandSeqMr range count
let str = map (bigString !!) nums
return str
The action can be used for example like this:
main = do
let
randomSeed = 4243 -- ideally passed from command line argument
gen0 = mkStdGen randomSeed -- for reproducibility of random numbers
baseString = ['a'..'z'] ++ ['0' .. '9']
strLen = 10
randomStringAction = makeRandomString baseString strLen
-- need just one random string:
(randomString1, gen1a) = runRand randomStringAction gen0
-- harder, need a list of 3 random strings:
act3 = do
-- "do construct" within the Random monad - not the IO monad
str1 <- randomStringAction
str2 <- randomStringAction
str3 <- randomStringAction
return [str1, str2, str3]
(threeRandomStrings, gen1b) = runRand act3 gen0
putStrLn $ "Single random string: " ++ randomString1
putStrLn $ "Three random strings: " ++ (show threeRandomStrings)
Single random string: x7sspkh6ai
Three random strings: ["x7sspkh6ai","cevyxt7mxh","07mryww0fv"]
Side note: if efficiency is a concern, you might want to use some Data.Map dictionary object to replace the map (bigString !!)
construct.
Upvotes: 1
Reputation: 33901
The implementation of the work around I mentioned:
Prelude> import System.Random
Prelude System.Random> gen <- newStdGen
Prelude System.Random> x = ['a'..'z'] ++ ['0' .. '9']
Prelude System.Random> fmap (x !! ) (take 10 $ randomRs (0, length x - 1 ) gen)
"h4tm52rfox"
Upvotes: 1