2013-04-28 68 views
3

我想为整数流中的每个元素生成一个随机数列表(0,1)。我试图建立一个理解列表:为无限列表中的每个元素生成随机数

randomNums = [(i, r) | i <- [1..], r <- SR.newStdGen] 

我简直无法弄清楚如何做到这一点。谁能帮忙?我正在寻找的输出是原始元素,我和一个相关的随机浮点数。例如:

[(1, 0.20381), (2, 0.1128373), ... 
+0

整数流是正常计数的流(如1,2,3等)还是它可以是任何整数序列? – 2013-04-28 15:37:05

+0

他们真的可以是任何东西,并以任何顺序。字符串,Ints等。我想为此列表中的每个项目创建一个随机浮点数。 – turtle 2013-04-28 15:48:49

回答

4

只需使用zip配对起来:

Prelude System.Random> let g = mkStdGen 42 

Prelude System.Random> take 10 . zip [1..] . randomRs (0.0,1.0) $ g 
[(1,0.11040701265689151),(2,0.8453984927258916),(3,0.30778213446209723),(4,0.781 
3880826070412),(5,0.5242581917029475),(6,0.5196911001158159),(7,0.20084688456283 
112),(8,0.47947729750989876),(9,0.3240164101179728),(10,6.1566369505963836e-2)] 

正如你所看到的,这些都不是真正随机的;相同的初始参数(在这里,42),相同序列将产生:

import System.Random 

randomNums :: [a] -> Int -> [(a, Float)] 
randomNums list initVal = zip list . randomRs (0.0,1.0) . mkStdGen $ initVal 

如果您使用此功能,从内main,还可以随机化initVal值本身,

main = do 
    .... 
    initVal <- randomIO :: IO Int 
    .... -- use initVal .... 
+0

这怎么能在主要功能中使用?代码在GHCi内部工作,但是当我尝试在main中运行时出错,如'print $ randomNums [1..10] 3' – turtle 2013-04-28 16:09:51

+0

@turtle我已经更改了类型签名。现在试试。 – 2013-04-28 16:10:37

2

首先,newStdGenIO StdGen,所以你不能在所有的纯函数中使用它,只有在IO单子。你可以让你的函数返回IO [(Int,Double)],但那不是很好,它会把所有东西都拉成IO。我建议你使用Rand monad代替:

randomNums :: RandomGen g => Rand g [(Int,Double)] 
randomNums = do 
    randDoubles <- getRandoms 
    return $ zip [1..] randDoubles 

或者干脆

randomNums = fmap (zip [1..]) getRandoms 

注意Rand比读者单子(又名功能)为随机生成多一点,这样你就可以轻松地把它改写无在MonadRandom包:只

randomNums :: RandomGen g => g -> [(Int,Double)] 
randomNums = zip [1..] . randoms 

,那signuature将不太愉快,如果你有多个娘家的东西用d随机生成器; monad会自动注意分配它们。随着明确的功能,你将不得不一直呼吁split,这很快就会变得混乱。

+0

感谢您的帮助。这看起来很清楚;但是,我收到错误。什么是'randoms'? 'zip [1 ..]。randoms'我也遇到了错误'randomNums = fmap(zip [1 ..])getRandoms'。什么是'getRandoms'? – turtle 2013-04-28 16:08:02

+0

['randoms ::(RandomGen g,Random a)=> g - > [a]'](http://www.haskell.org/hoogle/?hoogle=randoms)是基础包,你有已经(显然导入了合格的System.Random作为SR',所以它是'SR.randoms')。 ['getRandoms ::(Random a,MonadRandom m)=> m [a]'](http://hackage.haskell.org/packages/archive/MonadRandom/0.1.9/doc/html/Control-Monad-Random -Class.html)来自MonadRandom,你可能需要'cabal install'。 – leftaroundabout 2013-04-28 16:17:02

1

如果你想要一个纯粹的随机列表,然后使用WillNess的方法。如果你想要一个不纯的列表,然后使用pipes库懒洋洋地流不纯的列表:

import Control.Proxy 
import Control.Proxy.Trans.State 
import System.Random 

randomNums :: (Proxy p) =>() -> Producer p (Int, Double) IO r 
randomNums() = evalStateP 0 $ forever $ do 
    i <- get 
    r <- lift $ randomRIO (0, 1) 
    respond (i, r) 
    put $! i + 1 

您通过提供适当的转型和消费阶段宣读了名单。例如,如果你想采取的前10个元素,并打印出来,你写的:

>>> runProxy $ randomNums >-> takeB_ 10 >-> printD 
(0,0.2204881851502879) 
(1,0.2507730220341101) 
(2,0.8870240857313229) 
(3,0.5556581036216822) 
(4,0.6564558289397481) 
(5,0.7499290459359478) 
(6,0.10963804170328961) 
(7,9.475221797586297e-2) 
(8,9.342816284834865e-2) 
(9,0.23343178814756815) 

pipes为您提供了一种方式与effectful懒列表来工作,而无需牺牲采用高层次的转换操纵它们的能力。

+0

是'>>>'提示符? – 2013-04-28 16:08:48

+0

@WillNess是的,这应该是一个ghci提示。这只是我从编写黑道的习惯。 – 2013-04-28 16:11:08

+0

这可能会令人困惑。 :) 谢谢。 – 2013-04-28 16:11:53

相关问题