2014-10-17 4 views
2

Я хочу сгенерировать N случайных чисел между диапазоном с использованием randomR.Генерировать N случайных чисел, используя randomR

Я знаю, что есть и другие способы, чтобы выполнить эту задачу, такие как использование randomRs и с N, как в этом коде, который можно найти here:

diff_select :: Int -> Int -> StdGen -> [Int] 
diff_select n m = take n . nub . randomRs (1, m) 

, но я хочу сделать это с помощью randomR и с помощью State Монада. Я не знаю, где я заблуждаюсь с этим кодом:

let fs = \s -> (randomR (0, 5) s, s) 
let theState s = state (fs s) 
let rep n ma = replicateM n (theState ma) 
let res = runState (rep 3) (mkStdGen 4) -- Would like to use `get` 

Как я могу это сделать?

+0

Какое сообщение об ошибке вы получаете? Я знаю, что вы его получите, но при задании вопроса всегда следует публиковать любые ошибки, связанные с вашим кодом. – bheklilr

+0

Больше, чем ошибка, так как я думаю, что мой подход неверен, я просто хочу знать, как выполнить то, что я притворяюсь. – OneEyeQuestion

ответ

5

При использовании монады State для генерации случайных чисел вы хотите, чтобы ваше значение состояния являлось генератором. В этом случае мы можем просто использовать StdGen:

type RandGen a = State StdGen a 

Тогда вы можете написать вы действуете для генерации одной случайной величины

getRandom :: Random a => RandGen a 
getRandom = do 
    gen <- get 
    let (val, newGen) = random gen 
    put newGen 
    return val 

Теперь вы можете использовать для создания множества случайных чисел, используя все обычные Monad функции, такие как sequence, mapM и т. Д. Я дам вам реализовать эту часть. И, наконец, все, что вам нужно сделать, это выполнить код:

> runState getRandom (mkStdGen 42) :: (Int, StdGen) 

Если вы хотите, чтобы сделать его еще проще, функция state имеет следующий вид:

state :: MonadState s m => (s -> (a, s)) -> m a 

И random имеет тип

random :: (Random a, RandomGen g) => g -> (a, g) 

Обратите внимание, как s и g сек eem, чтобы выстроиться здесь? Вы можете фактически заменить getRandom на

getRandom :: Random a => RandGen a 
getRandom = state random 

И вся тяжелая работа делается для вас.

+0

Не отвечаю на вопрос: «Я хочу сделать это, используя * randomR * и [...] « – OneEyeQuestion

+2

Итак, как вы могли написать что-то очень, очень похожее на то, что я использую« randomR »? Каков тип' randomR'? – bheklilr

+0

Иначе говоря, я мог бы определить 'getRandomR', который является всего 2 символа без пробелов, отличных от 'getRandom', которые решают вашу проблему. Цель моего ответа состояла не в том, чтобы просто дать вам полное решение, но дать вам основу для его решения;) – bheklilr

0

Я думаю, что вы хотите:

let res = runState (rep 3) (mkStdGen 4) 

То, что вы написали, что эквивалентно:

runState (rep 3 (mkStdGen 4)) 

... который не то же самое thng.

+0

Не работает. Says: Не удалось совместить тип 't0 -> m0 [(a0, s0)] ' с' StateT StdGen Data.Functor.Identity.Identity a'. Отредактировано для исправления этой ошибки. Но все еще не работает. – OneEyeQuestion

 Смежные вопросы

  • Нет связанных вопросов^_^