我如何在函数中使用getStdGen

时间:2014-11-12 21:57:33

标签: haskell random

我是haskell的新手,特别是Random类型,当我遇到这个时,我正在查看learnyouahaskell教程

import System.Random  

main = do  
    gen <- getStdGen  
    putStr $ take 20 (randomRs ('a','z') gen) 

但是,当我尝试在函数中使用它时,这会失败(即)

genrandTF:: Int -> StdGen -> [Bool]
genrandTF number gen =  take number (randomRs (True, False) gen)

并通过

调用它
genrandTF 20 getStdGen

为什么会这样?

-update -

我得到的错误是

<interactive>:116:15:
    Couldn't match expected type `StdGen' with actual type `IO StdGen'
    In the second argument of `genrandTF', namely `(getStdGen)'
    In the expression: genrandTF 20 (getStdGen)

当我将其更改为输入IO StdGen时,由于收到此消息,我无法编译:

No instance for (RandomGen (IO StdGen))
  arising from a use of `randomRs'
In the second argument of `take', namely
  `(randomRs (True, False) gen)'
In the expression: take number (randomRs (True, False) gen)
In an equation for `genrandTF':
    genrandTF number gen = take number (randomRs (True, False) gen)

2 个答案:

答案 0 :(得分:4)

这是初学者的常见错误。 getStdGen是一个类型为IO StdGen的值;换句话说,它不是StdGen,而是一个计算机程序,当它完成时,它将包含Haskell可以用作StdGen的东西。

你需要运行程序来获取StdGen(通过unsafePerformIO - 顾名思义这会破坏Haskell中的几个安全保证),或者你需要结合使用与程序一起制作新程序。 (惯用法,Haskell I / O是一堆与I / O操作交织的Haskell操作。)

做你想做的最简单的方法是:

fmap (genrandTF 20) getStdGen

使用Functor的{​​{1}}实例。

答案 1 :(得分:-2)

来自randomR的{​​{1}}(randomRs内部使用):

  

未指定如果lo> hi

会发生什么

(在randomR (lo,hi)中调用时。

现在True > False,所以你在这里遇到了未指明的行为。尝试使用(False,True)(除了修复与IO相关的错误)。