>(–1352021624,651872571 1655838864)
Как и следовало ожидать! Тот же результат для тех же параметров. Так что давайте-ка передадим другой генератор в пара метре.
>ghci> random (mkStdGen 949494) :: (Int, StdGen)
>(539963926,466647808 1655838864)
Отлично, получили другое число. Мы можем использовать аннотацию типа для того, чтобы получать случайные значения разных типов.
>ghci> random (mkStdGen 949488) :: (Float, StdGen)
>(0.8938442,1597344447 1655838864)
>ghci> random (mkStdGen 949488) :: (Bool, StdGen)
>(False,1485632275 40692)
>ghci> random (mkStdGen 949488) :: (Integer, StdGen)
>(1691547873,1597344447 1655838864)
Давайте напишем функцию, которая эмулирует трёхкратное подбрасывание монеты. Если бы функция >random
не возвращала новый генератор вместе со случайным значением, нам пришлось бы передавать в функцию три случайных генератора в качестве параметров и затем возвращать результат подбрасывания монеты для каждого из них. Но это выглядит не очень разумным, потому что если один генератор может создавать случайные значения типа >Int
(а он может принимать довольно много разных значений), его должно хватить и на троекратное подбрасывание монеты (что даёт нам в точности восемь комбинаций). В таких случаях оказывается очень полезно, что функция >random
возвращает новый генератор вместе со значением.
Будем представлять монету с помощью >Bool
. >True
– это «орёл», а >False
–«решка».
>threeCoins :: StdGen –> (Bool, Bool, Bool)
>threeCoins gen =
> let (firstCoin, newGen) = random gen
> (secondCoin, newGen') = random newGen
> (thirdCoin, newGen'') = random newGen'
> in (firstCoin, secondCoin, thirdCoin)
Мы вызываем функцию >random
с генератором, который нам передали в параметре, и получаем монету и новый генератор. Затем снова вызываем функцию >random
, но на этот раз с новым генератором, чтобы получить вторую монету. Делаем то же самое с третьей монетой. Если бы мы вызывали функцию >random
с одним генератором, все монеты имели бы одинаковое значение, и в результате мы могли бы получать только >(False, False, False)
или >(True, True, True)
.
>ghci> threeCoins (mkStdGen 21)
>(True,True,True)
>ghci> threeCoins (mkStdGen 22)
>(True,False,True)
>ghci> threeCoins (mkStdGen 943)
>(True,False,True)
>ghci> threeCoins (mkStdGen 944)
>(True,True,True)
Обратите внимание, что нам не надо писать >random gen :: (Bool, StdGen)
: ведь мы уже указали, что мы желаем получить булевское значение, в декларации типа функции. По декларации язык Haskell может вычислить, что нам в данном случае нужно получить булевское значение.