我已经编写了一个函数来随机地从[-10,10]得到一对。
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'
答案 0 :(得分:5)
所以如果你想要的只是一个功能
randomPairs :: IO [(Int, Int)]
然后我们可以做类似的事情
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
monad中在IO
列表中使用它,以便最终得到
randomPairs = liftM2 zip randomList randomList
或者如果我们想要真正的幻想,我们可以使用应用程序而最终使用
import Control.Applicative
randomPairs = zip <$> randomList <*> randomList
但从您的randomNumber
功能判断,您真的只想要一个对。这个想法很相似。我们只使用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