我正在学习Haskell。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
该System.Random
模块提供了一些基本的原语,但是(我认为)它缺少适当的monadic接口。更确切地说,它提供了基于IO的monadic接口,但是缺少基于State的monadic接口。但是,后者很容易定义。
无论如何,如果要坚持使用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
上面的类型有点太多,这使我们无法rollDie
从非IO代码进行调用。一个State
基础的解决方案不会有这种limination
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
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句