有没有办法在Haskell中归纳多个生成器和随机数

时间:2018-06-23 05:24:34

标签: haskell generator generalization

我正在学习Haskell。 Average of large number of Dice Rolls in Haskell 我将如何使以下代码与多个骰子(例如8个骰子)一起工作,而不是反复创建let rolls..3,4,5 ... etc ...

module Dice where
import System.Random
import Data.List

dice = do
    g <- getStdGen
    b <- newStdGen
    let trials = 1000
    let rolls1 = take trials (randomRs (1,6) g :: [Int])
    let rolls2 = take trials (randomRs (1,6) b::[Int])
    let rolls = zipWith (+) rolls1 rolls2
    let average = div (foldl' (+) 0 rolls) trials
    print average

3 个答案:

答案 0 :(得分:4)

System.Random模块提供了一些基本的原语,但是(在我看来)它缺少适当的monadic接口。更准确地说,它提供了基于IO的monadic接口,但缺少基于State的monadic接口。不过,后者是easy to define

无论如何,如果要坚持使用IO和标准生成器,则可以编写:

-- (untested code)

rollDie :: Int -> IO Int
rollDie n = randomIO (1,n) -- implicitly uses the global generator

rollManyDice :: Int -> Int -> IO [Int]
rollManyDice howMany n = replicateM howMany (rollDie n)

main :: IO ()
main = do
   dice <- rollManyDice 20 6
   putStrLn $ "Here's 20 6-sides dice : " ++ show dice

其中replicateM执行howMany次单子动作,并将所有结果收集在一个列表中。这里的monad是IO,但可以是任何东西。

这是一种很好且简单的方法,但是上面的IO类型有点太多,使我们无法从非IO代码调用rollDie。基于State的解决方案将没有这种局限性

type R a = State StdGen a

rollDie :: Int -> R Int
rollDie n = state $ randomR (1,n) -- uses the generator inside the State monad

rollManyDice :: Int -> Int -> R [Int]
rollManyDice howMany n = replicateM howMany (rollDie n)

main :: IO ()
main = do
   g <- getStdGen
   let dice = evalState (rollManyDice 20 6) g
   putStrLn $ "Here's 20 6-sides dice : " ++ show dice

答案 1 :(得分:0)

按照目前的公式,您只需要合计k * N个单个骰子,然后将它们除以N,其中k是您要“同时”掷骰子的数量,N数量试验。将单个骰子中的所有骰子相加,然后将所有骰子相加,与将所有骰子总和相加。

如果您要使其复杂,那么,使单个多辊列表具有指定长度的随机值,将其求和(您可以使用普通sum,即使k不太大也可以不进行优化),计算平均值结果。

答案 2 :(得分:0)

module Dice where
import System.Random
import Data.List
import Control.Applicative
import Control.Monad

rollDie :: Int -> IO Int
rollDie n = randomRIO (1,n)

rollManyDice :: Int -> Int -> IO [Int]
rollManyDice howMany n = replicateM howMany (rollDie n)

dice2 = do
    dice <- rollManyDice 8 6
    putStrLn $ "Here's 20 -6 sided dice: " ++show dice