Читаем Учебник по Haskell полностью

Функции для создания случайных значений определены в модуле System.Random. Модуль System.Random

входит в библиотеку random. Если в вашей поставке ghc его не оказалось, вы можете установить его вручную

через интернет, набрав в командной строке cabal install random. Сначала давайте разберёмся как гене-

рируются случайные числа. Стандартные случайные числа очень похожи на те, что были у нас, когда мы

рассматривали примеры специальных функций. У нас есть генератор случайных чисел типа g и с помощью

функции next мы можем получить обновлённый генератор и случайное целое число:

next :: g -> (Int, g)

Не правда ли этот тип очень похож на тип результата функций с состоянием. В качестве состояния теперь

выступает генератор случайных чисел g. Это поведение описывается классом RandomGen:

class RandomGen g where

next

:: g -> (Int, g)

split

:: g -> (g, g)

geтRange :: g -> (Int, Int)

Функция next обновляет генератор и возвращает случайное значение типа Int. Функция split раска-

лывает один генератор на два. Функция genRange возвращает диапазон значений генерируемых случайных

чисел. Первое значение в паре результата genRange должно быть всегда меньше второго. Для этого класса

определён один экземпляр, это тип StdGen. Мы можем создать первый генератор по целому числу с помощью

функции mkStdGen:

mkStdGen :: Int -> StdGen

Давайте посмотрим как это происходит в интерпретаторе:

Типичные задачи IO | 133

Prelude> :m System.Random

Prelude System.Random> let g0 = mkStdGen 0

Prelude System.Random> let (n0, g1) = next g0

Prelude System.Random> let (n1, g2) = next g1

Prelude System.Random> n0

2147482884

Prelude System.Random> n1

2092764894

Мы создали первый генератор, а затем начали получать новые. Для того, чтобы получать новые случайные

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

с состоянием и пользоваться методами классов Functor, Applicative и Monad. Обновление генератора будет

происходить за ширмой, во время применения функций. Но у нас есть и другой путь.

Вместо монады State мы можем воспользоваться монадой IO. Если нам лень определять генератор слу-

чайных чисел, мы можем попросить компьютер определить его за нас. В этом случае мы взаимодействуем с

компьютером, мы запрашиваем глобальное для системы случайное значение, поэтому возвращаемое значе-

ние будет завёрнуто в тип IO. Для этого определены функции:

getStdGen :: IO StdGen

newStdGen :: IO StdGen

Функция getStdGen запрашивает глобальный для системы генератор случайных чисел. Функция

newStdGen не только запрашивает генератор, но также и обновляет его. Мы пользуемся этими функци-

ями так же как и mkStdGen, только теперь мы спрашиваем первый аргумент у компьютера, а не передаём его

вручную. Также есть ещё одна полезная функция:

getStdRandom

:: (StdGen -> (a, StdGen)) -> IO a

Посмотрим, что получится, если передать в неё функцию next:

Prelude System.Random> getStdRandom next

1386438055

Prelude System.Random> getStdRandom next

961860614

И не надо обновлять никаких генераторов. Но вместо одного неудобства мы получили другое. Теперь

значение завёрнуто в оболочку IO.

Генератор StdGen делает случайные числа из диапазона всех целых чисел. Что если мы хотим получить

только числа из некоторого интервала? И как получить случайные значения других типов? Для этого суще-

ствует класс Random. Он является удобной надстройкой над классом RandomGen. Посмотрим на его основные

методы:

class Random a where

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

random

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

Метод randomR принимает диапазон значений, генератор случайных чисел и возвращает случайное число

из указанного диапазона и обновлённый генератор. Метод random является синонимом метода next из класса

RandomGen, только теперь мы можем получать не только целые числа.

Есть и дополнительные методы. Есть методы, которые позволяют генерировать список всех возможных

случайных значений для данного генератора:

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

randoms

:: RandomGen g => g -> [a]

За счёт лени мы будем получать новые значения по мере необходимости.

randomRIO

:: (a, a) -> IO a

randomIO

:: IO a

Эти функции выполняют тоже, что и основные функции класса, но им не нужен генератор случайных

чисел, они создают его с помощью функции getStdRandom. Экземпляры Random определены для Bool, Char,

Double, Float, Int и Integer. Например так мы можем подбросить кости десять раз:

134 | Глава 8: IO

Prelude System.Random> fmap (take 10 . randomRs (1, 6)) getStdGen

[5,6,5,5,6,4,6,4,4,4]

Prelude System.Random> fmap (take 10 . randomRs (1, 6)) getStdGen

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных