2014-02-18 3 views
2

Я написал функцию для получения пары из [-10,10] случайным образом.Haskell: Случайное число

import System.Random 


main = 
    do { 
     s <- randomNumber 
     ; b <- randomNumber 
     ; print (head s,head b)} 
randomNumber :: IO [Int] 
randomNumber = sequence $ replicate 1 $ randomRIO (-10,10) 

Теперь я хочу взять список как [(1,2), (2,3), (2,3)], все число, пришедшие из randomNumber. Как я могу это сделать? Я не знаю, как это достичь.

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

import System.Random 
import Control.Monad.State 
randomSt :: (RandomGen g, Random a) => State g a 
randomSt = State random 

Но когда я собирал его, он показал: Не в области видимости: конструктор данных «State»

ответ

5

Так что, если все, что вы хотите, это функция

затем мы можем сделать что-то вроде

randomList :: IO [Int] 
    randomList = randomRs (-10, 10) `fmap` newStdGen 
    randomPairs = ??? randomList randomList 

где ??? занимает два IO [Int] и "молнии" их вместе, чтобы сформировать IO [(Int, Int)]. Обратимся теперь к hoogle и запрос для функции [a] -> [a] -> [(a, a]) и мы находим функцию zip :: [a] -> [b] -> [(a, b)] теперь мы просто нужно «поднять» zip в IO монады, чтобы работать с ним через IO списки, чтобы мы в конечном итоге с

randomPairs = liftM2 zip randomList randomList 

или если мы хотим быть действительно фантазии, мы могли бы использовать вместо аппликативных и в конечном итоге с

import Control.Applicative 

    randomPairs = zip <$> randomList <*> randomList 

Но, судя по вашему randomNumber Funciton, вы действительно просто хотите один пару. Идея очень похожа. Вместо создания списка, мы генерируем только одно случайное число с randomRIO (-10, 10) и поднимите (,) :: a -> b -> (a, b) в результате

randomPair = (,) <$> randomRIO (-10, 10) <*> randomRIO (-10, 10) 

Наконец, конструктор State данных ушел некоторое время назад, потому что MTL переехал из имеющих отдельные State и StateT типов, чтобы сделать State - синоним типа. В настоящее время вы должны использовать нижний регистр state :: (s -> (s, a)) -> State s a

Чтобы уточнить, мой окончательный код

import System.Random 
import Control.Monad 

randomList :: IO [Int] 
randomList = randomRs (-10, 10) `fmap` newStdGen 

pairs :: IO [(Int, Int)] 
pairs = liftM2 zip randomList randomList 

somePairs n = take n `fmap` pairs 

main = somePairs 10 >>= print 
+0

Как вы можете видеть, я импортировал Control.Monad.State, то я до сих пор не могу его использовать. – Xie

+0

@Xie Моя ошибка, я обновил свой ответ соответственно – jozefg

+0

Привет, ваш код передал компиляцию, но когда я запустил его, он отображает память. Похоже, что что-то не так с randomList? – Xie

Смежные вопросы