我的目标是编写一个函数,根据种子生成给定长度的随机字符串(字母数字)。重要的是,结果不仅是字符串,还包括新种子。
我知道我可以通过使用take on randomRS获得一个字符串,但问题是我之后无法检索种子
generate :: StdGen -> String -> (String, StdGen)
我能够为一个角色编写它,虽然我无法获得允许字母和数字的范围
generateRandomCharacter gen = randomR ('a','z') gen
答案 0 :(得分:3)
最好的技巧是使用“拆分”:
class RandomGen g where
split :: g -> (g,g)
-- Other functions as well.
将您的随机生成器分成两部分。使用其中一个结果生成随机字符串,并返回另一个结果。
从你的问题不清楚字符串应该是多长时间:大概它应该与输入字符串的长度相同。如果是这样,那么以Int长度作为参数将是更好的风格。
你还说你还没有弄清楚如何从一个更复杂的范围中选择('a','z')。您需要设置一个候选项目的数组(或更好的矢量)并从中选择一个。您可以使用列表,但这意味着您每次都会遍历列表。
答案 1 :(得分:3)
replicateM
。
generateR :: (MonadRandom m, Random a) => Int -> (a, a) -> m [a]
generateR len range = replicateM len (getRandomR range)
答案 2 :(得分:1)
一种方法是将您感兴趣的可用字符定义为数组,然后从数组中随机选择字符。
randomEl :: RandomGen g => [a] -> g -> (a, g)
randomEl xs g -> (g', xs !! r)
where (r, g') = randomR (0, length xs - 1) g
randomAlphaNum :: RandomGen g => g -> (Char, g)
randomAlphaNum = randomEl (['0'..'9'] ++ ['a'..'z'])
接下来构建字符串应该非常简单......例如,Prelude中定义了iterate。
generate :: RandomGen g => Int -> g -> (String, g)
generate n g = (map fst iterations, (snd . last) iterations)
where iterations = (take n . iterate (randomAlphaNum . snd)) (randomAlphaNum g)