newtype State = State Integer deriving Show -- как data, но эффективней newtype Random a = Random (State -> (a, State)) nextState :: Integer -> Integer --nextState x0 = mod (134775813*x0 + 1) (2^32) nextState x0 = mod (25214903917*x0 + 11) (2^48) -- возвращает случайное значение и превращает старое состояние в новое generate :: Random a -> State -> (a, State) -- generate (Random f) state = f state generate (Random f) = f -- ползволяет сгенерировать N значений в списке из одного генератора. generateN :: Random a -> Int -> State -> ([a], State) generateN _ 0 state = ([], state) generateN random n state = (h : t, finalState) where (h, nextState) = generate random state (t, finalState) = generateN random (n - 1) nextState randomInRange :: Integer -> Integer -> Random Integer randomInRange min max = Random $ \(State x0) -> (min + (x0 `div` (2^16) `mod` (max - min + 1)), State $ nextState x0) -- тестируем генерацию чисел random_1_10 = randomInRange 1 10 state = State 13434 let (x, nextState) = generateN random_1_10 10 state x nextState instance Functor Random where -- g :: State -> a, f :: a -> b fmap f random = Random $ \state -> (let (val, s2) = generate random state in (f val, s2) ) random_0_1 = randomInRange 0 1 data Coin = Head | Tail deriving Show genHeadTail = (\x -> if x == 0 then Head else Tail) <$> random_0_1 generateN genHeadTail 10 (State 1244) generateN random_0_1 10 (State 1244) generate genHeadTail (State 123) generate random_0_1 (State 123) instance Applicative Random where -- делает из обычного значения случайное, это генератор всегда одного значения pure x = Random (\state -> (x, state)) randomF <*> randomVal = Random (\state -> let (f, state2) = generate randomF state (val, state3) = generate randomVal state2 in (f val, state3) ) import Control.Applicative random10plus10 = liftA2 (+) random_1_10 random_1_10 -- или random10plus10 = (+) <$> random_1_10 <*> random_1_10 generateN random10plus10 100 (State 1) instance Monad Random where random >>= f = Random (\state -> let (randomVal, state2) = generate random state (val, nextState) = generate (f randomVal) state2 in (val, nextState)) r = do a <- randomInRange 0 1 b <- randomInRange 0 1 c <- randomInRange 0 1 return $ a + b + c generateN r 100 (State 2)