Haskell и случайные числа

Я смешивал с Haskell несколько дней и споткнулся в проблему.

Мне нужен метод, который возвращает случайный список целых чисел (Rand [[Интервал]]).

Так, я определил тип: type Rand a = StdGen -> (a, StdGen). Я смог произвести Rand IO Integer и Rand [IO Integer] ( (returnR lst) :: StdGen -> ([IO Integer], StdGen) ) так или иначе. Любые подсказки, как произвести Rand [[Int]]?

17
задан Indrek 29 April 2010 в 15:27
поделиться

4 ответа

Как избежать ввода-вывода зависит от того, почему он вообще вводится. Хотя генераторы псевдослучайных чисел по своей сути ориентированы на состояние, нет никаких причин для участия IO .

Я собираюсь предположить, что вы используете newStdGen или getStdGen , чтобы получить начальный ГПСЧ. Если это так, то полностью избежать IO невозможно. Вместо этого вы можете напрямую заполнить PRNG с помощью mkStdGen , помня, что одно и то же начальное значение приведет к той же "случайной" числовой последовательности.

Скорее всего, вы хотите получить ГПСЧ внутри IO , а затем передать его в качестве аргумента чистой функции. В конце, конечно же, все будет заключено в IO , но промежуточным вычислениям это не понадобится. Вот краткий пример, чтобы дать вам представление:

import System.Random

type Rand a = StdGen -> (a, StdGen)

getPRNG = do
    rng <- newStdGen
    let x = usePRNG rng
    print x

usePRNG :: StdGen -> [[Int]]
usePRNG rng = let (x, rng') = randomInts 5 rng
                  (y, _) = randomInts 10 rng'
              in [x, y]

randomInts :: Int -> Rand [Int]
randomInts 0 rng = ([], rng)
randomInts n rng = let (x, rng') = next rng
                       (xs, rng'') = randomInts (n - 1) rng'
                   in (x:xs, rng'')

Вы могли заметить, что код, использующий ГПСЧ, становится довольно уродливым из-за постоянной передачи текущего значения туда и обратно. Это также потенциально подвержено ошибкам, поскольку было бы легко случайно повторно использовать старое значение. Как упоминалось выше, использование одного и того же значения PRNG даст одинаковую последовательность чисел, что обычно не то, что вам нужно. Обе задачи являются прекрасным примером того, где имеет смысл использовать монаду State - что здесь не по теме, но вы, возможно, захотите изучить ее позже.

20
ответ дан 30 November 2019 в 11:26
поделиться

Используя монадическую нотацию, вы должны иметь возможность написать что-то вроде

randomList gen = do
    randomLength <- yourRandomInteger
    loop gen (randomLength + 1)
 where
    loop gen 1 = gen
    loop gen n = do { x <- gen; xs <- loop gen (n - 1); return (x:xs) }

А с этим

randomInts :: Rand [Int]
randomInts = randomList yourRandomInteger

randomLists :: Rand [[Int]]
randomLists = randomList randomInts

Что касается самих монадических вычислений, взгляните на в этой статье . Обратите внимание, что генераторы случайных чисел являются чистыми, вам не нужны какие-либо IO только для этой цели.

3
ответ дан 30 November 2019 в 11:26
поделиться

Если вы хотите получить бесконечный список Integer s, вы столкнетесь с проблемами, так как вы никогда не получите значение StdGen . обратно. Здесь вы хотите разделить StdGen сначала, передать одну половину снова и «использовать» другую половину для создания бесконечного списка целых чисел. Примерно так:

infiniteRandomInts :: Rand [Int]
infiniteRandomInts g = (ints, g2) where
    (g1,g2) = split g
    ints = randoms g1

Однако, если вы затем повторите этот подход, чтобы получить бесконечную матрицу Integer s (что вам, кажется, нужно, используя Rand [[Int]] ), вы можете столкнуться с проблемами статистического характера: я не знаю, насколько хорошо StdGen справляется с повторным разбиением тингом. Может быть, другая реализация RandomGen могла бы быть лучше, или вы могли бы попытаться использовать какой-то диагональный обход, чтобы превратить [Int] в [[Int]] .

6
ответ дан 30 November 2019 в 11:26
поделиться

Вы воссоздаете MonadRandom на сайте Hackage. Если это больше, чем просто эксперимент, чтобы проверить, сможете ли вы это сделать, вы можете вместо этого использовать эту библиотеку.

11
ответ дан 30 November 2019 в 11:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: