【问题标题】:Haskell: Random numberHaskell:随机数
【发布时间】:2014-02-18 21:46:15
【问题描述】:

我写了一个函数来随机从 [-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'

【问题讨论】:

    标签: haskell


    【解决方案1】:

    如果你想要的只是一个函数

      randomPairs :: IO [(Int, Int)]
    

    然后我们可以做类似的事情

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

    其中??? 需要两个IO [Int] 并将它们“压缩”在一起以形成IO [(Int, Int)]。我们现在转向hoogle 并查询函数[a] -&gt; [a] -&gt; [(a, a]),我们找到了一个函数zip :: [a] -&gt; [b] -&gt; [(a, b)],我们现在只需要将zip“提升”到IO monad 以便在IO 列表中使用它,所以我们最终得到了

      randomPairs = liftM2 zip randomList randomList
    

    或者如果我们想要真正花哨,我们可以使用 applicatives 来代替

      import Control.Applicative
    
      randomPairs = zip <$> randomList <*> randomList
    

    但是从您的randomNumber 功能来看,您真的只想要一个 对。这个想法非常相似。我们没有生成一个列表,而是只生成一个带有randomRIO (-10, 10) 的随机数并提升(,) :: a -&gt; b -&gt; (a, b) 导致

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

    最后,State 数据构造函数不久前消失了,因为 MTL 从具有单独的 StateStateT 类型转变为使 State 成为类型同义词。现在你需要使用小写的state :: (s -&gt; (s, a)) -&gt; 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
    

    【讨论】:

    • 可以看到,我已经导入了Control.Monad.State,然后还是不能用。
    • 您好,您的代码通过了编译,但是当我运行它时,它显示内存不足。看起来随机列表有问题?
    • @Xie 确实,我已经更新以利用newStdGenrandomRs,从类型上应该很清楚它是如何工作的
    • 嗨,这个新代码实际上每对都得到相同的数字。我将您的最后一个代码更改为 randomList = sequence . replicate 1$ randomRIO (-10, 10) randomPairs = zip &lt;$&gt; randomList &lt;*&gt; randomLis ,它得到了很好的一对。实际上,我想为 [-10,10] 获得 n 对,并且 n 是受控的。我怎样才能做到这一点?
    • 喜欢take n randomPairs,但看起来类型是错误的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    相关资源
    最近更新 更多