哈斯克尔随机生成 [英] Haskell Random Generation

查看:119
本文介绍了哈斯克尔随机生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 类型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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆