哈斯克尔随机生成 [英] Haskell Random Generation
问题描述
类型Rand a =状态StdGen a
可以有人描述以下类型的构造函数和函数是如何工作的?
getRandom ::(Random a)=>兰德a
getRandom = get>> =(\r-> let(a,g)= random r in(put g)>>(return a))
runRand :: Int - > Rand a - > a
runRand n r = evalState r $ mkStdGen n
runRandIO :: Rand a - > IO a
runRandIO r = randomIO>> =(\ rnd - > return $ runRand rnd r)
getRandoms ::(Random a)=> Int - > Rand [a]
getRandoms n = mapM(\_-> getRandom)[1..n]
<
type Rand a = State StdGen a
这一行告诉你 Rand a
是 State 类型的类型同义词,其状态由
StdGen
给出,并且其最终值是type A
。这将用于存储每个随机数请求之间随机数生成器的状态。
代码 getRandom
可以转换成符号:
getRandom ::(Random a)=> Rand a
getRandom = do
r< - get - 获取生成器的当前状态
let(a,g)=随机r在do中调用函数random :: StdGen - > (a,StdGen)
放g - 存储生成器的新状态
返回a - 返回生成的随机数
$ b $ runRand
函数需要一个初始种子 n
和一个值 r
类型 Rand a
(记住,它只是 State StdGen的同义词一个
)。它使用 mkStdGen n
创建一个新的生成器,并将它提供给 evalState r
。函数 evalState
只是计算状态sa
类型的返回值,忽略状态。 同样,我们可以将 runRandIO
转换为 do
表示法:
runRandIO :: Rand a - > IO a
runRandIO r = do
rnd < - randomIO - 使用randomIO生成一个新的随机数
return(runRand rnd r) - 使用该数字作为runRand的初始种子
最后, getRandoms
取一个数字 n
表示要生成的随机值的数量。它建立一个列表 [1..n]
并将 getRandom
应用到列表中。请注意, [1..n]
中的实际值未使用(您可以看出,因为lambda函数以 \_ - >开头; ...
)。该列表只是为了拥有正确数量的元素。由于 getRandom
返回一个monadic值,我们使用 mapM
来映射列表,这会导致状态(即 StdGen
)通过对 getRandom
的每次调用进行正确的线程化。
Could someone describe how the following type constructor and functions work?
type Rand a = State StdGen a
getRandom :: (Random a) => Rand a
getRandom = get >>= (\r -> let (a,g) = random r in (put g) >> (return a))
runRand :: Int -> Rand a -> a
runRand n r = evalState r $ mkStdGen n
runRandIO :: Rand a -> IO a
runRandIO r = randomIO >>= (\rnd -> return $ runRand rnd r)
getRandoms :: (Random a) => Int -> Rand [a]
getRandoms n = mapM (\_ -> getRandom) [1..n]
Let's start at the beginning:
type Rand a = State StdGen a
This line tells you that Rand a
is a type synonym for a State
type, whose state is given by StdGen
and whose eventual value is of type a
. This will be used to store the state of the random number generator between each request for a random number.
The code for getRandom
can be converted into do notation:
getRandom :: (Random a) => Rand a
getRandom = do
r <- get -- get the current state of the generator
let (a,g) = random r in do -- call the function random :: StdGen -> (a, StdGen)
put g -- store the new state of the generator
return a -- return the random number that was generated
The runRand
function takes an initial seed n
and a value r
of type Rand a
(which, remember, is just a synonym for State StdGen a
). It creates a new generator with mkStdGen n
and feeds it to evalState r
. The function evalState
just evaluates the return value of a State s a
type, ignoring the state.
Again, we can convert runRandIO
into do
notation:
runRandIO :: Rand a -> IO a
runRandIO r = do
rnd <- randomIO -- generate a new random number using randomIO
return (runRand rnd r) -- use that number as the initial seed for runRand
Finally, getRandoms
takes a number n
representing the number of random values that you want to generate. It builds a list [1..n]
and applies getRandom
to the list. Note that the actual values in [1..n]
aren't used (you can tell because the lambda function starts with \_ -> ...
). The list is just there to have something with the correct number of elements. Since getRandom
returns a monadic value, we use mapM
to map over the list, which causes the state (i.e. StdGen
) to be threaded correctly through each of the calls to getRandom
.
这篇关于哈斯克尔随机生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!