Главная » Haskell » Модуль Random

0

содержит определения программных сущностей для работы со случайными числами. Использование:

import System.Random

В модуле описано два класса для представления генераторов случайных величин и для представления самих случайных величин. Также описан специальный тип данных, представляющий собой обобщённый генератор случайных величин. Ну и наконец, определены пять утилитарных функций для работы со случайными значениями.

Рассматриваемый модуль предлагает решение общей проблемы по генерации псевдослучайных чисел. Функции в этом модуле позволяют генерировать последовательности повторяющихся значений при  помощи начального элемента (генератора). Либо можно использовать системный генератор для получения неповторяющихся значений при каждом запуске.

Библиотека разбита на два слоя. На первом находится ядро генератора случайных чисел, которое работает на битовом уровне. Класс RandomGen предоставляет базовый интерфейс к таким генераторам. Второй слой — класс Random, который является интерфейсом для получения конкретных значений из генератора случайных чисел. Например, экземпляр этого класса для типа Float будет генерировать случайные числа типа Float.

Реализация системного генератора использует технологию, описанную в [14] для 32-битных архитектур. Эта технология позволяет  генерировать псевдослучайные последовательности  с периодом  примерно 2.3058418. Дополнительные данные по генераторам случайных чисел в рамках функциональной парадигмы можно найти в работах [3, 4, 7, 20].

Класс: RandomGen

Описание: представляет обобщённый интерфейс для генераторов случайных значений.

Определение:

class  RandomGen  g  where

next          :: g  ->  (Int,  g) split   :: g  ->  (g, g) genRange  :: g  ->  (Int, Int)

Метод next возвращает очередное целочисленное случайное значение, которое равномерно распределено в интервале, который возвращается методом genRange (включая конечные точки), а также новое значение генератора. Соответственно, метод genRange возвращает пару значений, являющихся нижней и верхней границей интервала, внутри которого происходит выборка случайных чисел. Этот метод не является строгим, что означает, что метод не вычисляет своего аргумента (не использует его), а потому  единственный вызов метода может быть использован для получения интервала без опасения того, что для нового генератора, полученного при помощи метода next, интервал будет новый.

Метод split позволяет получить два различных генератора  случайных величин на основе одного входного. Этот метод весьма  полезен в функциональных алгоритмах, поскольку позволяет передавать генераторы случайных величин в рекурсивные деревья вызова.

Единственным экземпляром этого класса является тип StdGen.

Тип: StdGen

Описание: абстрактный тип, представляющий обобщённый генератор случайных чисел. Интервал, используемый для генерации случайных чисел, входит в размер 30 бит.

Определение:

data  StdGen =  StdGen Int Int

Данный тип имеет экземпляры следующих классов: RandomGen, Read и Show.

Функция: mkStdGen

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

Определение:

mkStdGen  :: Int ->  StdGen

mkStdGen  s  | s  < 0         = mkStdGen  (-s)

| otherwise = StdGen (s1  + 1)  (s2  + 1)

where

(q, s1)  = s  ‘divMod‘  2147483562 s2           = q  ‘mod‘  2147483398

Класс:  Random

Описание: позволяет получать случайные значения различных типов. Обязательному определению подлежат методы random и randomR.

Определение:

class Random  a where

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

randomRs  :: RandomGen  g => (a, a)  ->  g  ->  [a] randoms     :: RandomGen  g => g  ->  [a]

randomRIO  :: (a, a)  ->  IO a randomIO    ::  IO a

Метод randomR получает  на вход пару, представляющую нижнюю и верхнюю границы интервала, а также генератор случайных величин. Возвращает случайное значение, равномерно распределённое в заданном интервале, а также новое значение генератора. В свою очередь метод random выполняет те же самые действия, но в качестве интервала выборки берёт интервал, заданный для типа генератора по умолчанию методом genRange класса RandomGen.

Метод randomRs является вариантом  метода randomR, возвращающим бесконечный список случайных значений. Также и метод randoms является таким же вариантом метода random. Наконец, методы randomRIO и randomIO для генерации случайных чисел используют глобальный генератор, а значения возвращают в монаде IO.

Экземплярами  класса  являются  типы:  Bool,   Char,  Double,   Float,   Int

и Integer.

Функция: getStdRandom

Описание: использует заданную функцию для получения случайного  значения из текущего глобального генератора, а также обновляет глобальный генератор

новым, который  возвращён функцией. Поскольку эта функция  использует побочные эффекты, она определена в монаде IO.

Определение:

getStdRandom :: (StdGen ->  (a,  StdGen))  ->  IO a getStdRandom f = do  rng  < getStdGen

let (v,  new_rng)  = f  rng setStdGen  new_rng

return  v

Использование этой функции достаточно просто. Например, для получения случайного числа в интервале от 1 до 6 (для эмуляции  игры в кости) можно воспользоваться следующей функцией:

rollDice  ::  IO  Int

rollDice = getStdRandom  (randomR (1, 6))

Функция: getStdGen

Описание: возвращает глобальный генератор случайных чисел.

Определение:

getStdGen  :: IO  StdGen

getStdGen   =  readIORef theStdGen

Функция: setStdGen

Описание: устанавливает глобальный генератор случайных чисел.

Определение:

setStdGen ::  StdGen ->  IO ()

setStdGen sgen = writeIORef  theStdGen sgen

Функция: newStdGen

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

newStdGen  :: IO  StdGen

newStdGen  = do rng  <getStdGen

let (a, b)  = split  rng setStdGen  a

return b

Источник: Душкин Р. В., Справочник по языку Haskell. М.: ДМК Пресс, 2008. 544 с., ил.

По теме:

  • Комментарии