【问题标题】:How to use random numbers within recursion?如何在递归中使用随机数?
【发布时间】:2014-06-11 08:51:40
【问题描述】:

我正在尝试从列表中选择一个随机元素,但这会使函数不纯,因此无法编译。我应该怎么做才能让递归函数接受一个 IO 动作?

build :: Jabberwocky Integer String Syllables -> String
build (Jabberwocky 0 body syl) = body
build (Jabberwocky len body syl)
    | syl == Middle     = build (Jabberwocky (len - 1) (body ++ (rand middle)    ) Consonant)
    | syl == Consonant  = build (Jabberwocky (len - 1) (body ++ (rand consonant)) Vowel)
    | syl == Vowel      = build (Jabberwocky (len - 1) (body ++ (rand vowel)     ) Consonant)
    | syl == Ending     = build (Jabberwocky (len - 1) (body ++ (rand ending)    ) Vowel)
        where 
            rand = getStdRandom (randomR (1,6))

【问题讨论】:

  • 您可以以纯粹的方式生成随机数,根本不需要IO。你只需要传递你自己的生成器对象而不是使用全局对象。如果您坚持使用IO,那么您的签名应该显示它(但我不会这样做)。
  • 您能详细说明一下吗?到目前为止,我寻找的答案恰恰相反。 stackoverflow.com/questions/2926267/…
  • 不相反,正是我的意思。 Jabberwocky ... -> String 是一个纯函数。你不能在里面使用IO。您需要将函数更改为不纯函数 (Jabberwocky ... -> IO String) 或停止使用全局随机数生成器。
  • 抱歉这个菜鸟问题。我还是很困惑。如何用 monad 编写函数?

标签: haskell recursion random


【解决方案1】:

您必须将生成器带入纯进程(链接新的随机生成器状态)

randomR_nTimes_rec :: (RandomGen g, Random a) => Int -> (a, a) -> g -> ([a], g)
randomR_nTimes_rec 0 _ g = ([], g)
randomR_nTimes_rec n i g = (x:xs, g'') where ( x, g' ) = randomR i g
                                             (xs, g'') = randomR_nTimes_rec (n - 1) i g'

用法

*Main> getStdGen  >>= return . randomR_nTimes_rec 5 (0,5)
([2,5,3,1,3],1206240749 652912057)

如果你应该将随机状态带入一个复杂的过程中可能会有用Control.Monad.Randomwith example

【讨论】:

  • 我不认为这个答案增加了副本中的答案之外的任何内容。下次考虑近距离投票并回答最初的问题。
  • @BartekBanachewicz(好吧,它是重复的,让我“说反话”让我感到困惑......)。
  • 我只想补充一点,如果您手动线程化生成器,请非常小心不要两次使用同一个生成器。这比您想象的要容易得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 2019-08-03
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多