【问题标题】:Problems to make a function that rollsNDice in Haskell在 Haskell 中创建滚动NDice 的函数的问题
【发布时间】:2019-11-05 11:31:08
【问题描述】:

我正在 Haskell 中试验随机性,我想做一个函数,给定 Int n 返回 1 到 6 之间随机数状态的列表:

-- auxiliar function
rollDie :: State StdGen Int
rollDie = do generator <- get
                let (value, newGenerator) = randomR (1,6) generator
                put newGenerator
                return value

rollNDice :: Int -> State StdGen [Int]
rollNDice n | n == 0    = [] :: State StdGen [Int]
  | otherwise = (:) <$> rollDie <*> rollNDice (n-1)

但是当我尝试在 ghci 中运行它时,我得到:

Couldn't match type ‘[a0]’
                     with ‘StateT StdGen Data.Functor.Identity.Identity [Int]’
      Expected type: State StdGen [Int]
        Actual type: [a0]
    • In the expression: [] :: State StdGen [Int]
      In an equation for ‘rollNDice’:
          rollNDice n
            | n == 0 = [] :: State StdGen [Int]
            | otherwise = (:) <$> rollDie <*> rollNDice (n - 1)

我不明白这个错误。有什么想法吗?

【问题讨论】:

  • 你应该使用return [],或者pure []

标签: haskell random state


【解决方案1】:

这不起作用的原因是因为[] 的类型为[a],您不能使用[] :: State StdGen [Int] 将其转换为State StdGen [Int]

但是,您可以使用 pure :: Applicative m =&gt; a -&gt; m a 将其包装在 State StdGen [Int] 中:

rollNDice :: Int -> State StdGen [Int]
rollNDice 0 = pure []
rollNDice n = (:) <$> rollDie <*> rollNDice (n-1)

话虽如此,您可以在这里使用replicateM :: Applicative m =&gt; Int -&gt; m a -&gt; m [a] 来生成n 项目列表:

import Control.Monad(replicateM)

rollNDice :: Int -> State StdGen [Int]
rollNDice = (`replicateM` rollDie)

例如:

Prelude System.Random Control.Monad.Trans.State Control.Monad> evalState (rollNDice 5) (mkStdGen 0)
[6,6,4,1,5]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    相关资源
    最近更新 更多