Haskell随机IO到Int

Mel*_*own 3 random io monads haskell functional-programming

我最近选择了Haskell,语法对我来说真的很混乱.我试图使用0到51之间的随机数

randomRIO (0, 51)
Run Code Online (Sandbox Code Playgroud)

但我不知道如何使它成为一个实际的Int(现在它的类型IO a).我相信你应该能做到:

gen <- randomRIO (0, 51)
Run Code Online (Sandbox Code Playgroud)

然后gen应该是一个Int,但我必须在do块中这样做?如何创建获取此函数并返回Int的函数.从googeling我害怕有一些我不理解的基本知识.我完全迷失了.

luq*_*qui 16

是的,有一些基本的东西,这是新的Haskellers最常见的事情.基本上,你说的一切都是正确的,如果你想要一个返回随机int的"函数",你就不能拥有它.

你可以做

main :: IO ()
main = do
    num <- getRandomR (0, 51)
    putStrLn ("The number is " ++ show num)
Run Code Online (Sandbox Code Playgroud)

你也可以把它考虑出来

getCardIndex :: IO Int
getCardIndex = do
    ix <- getRandomR (0,51)
    return (ix + 1)   -- just as an example of how you can transform it

main :: IO ()
main = do
    card <- getCardIndex
    putStrLn ("The number is " ++ show card)
Run Code Online (Sandbox Code Playgroud)

你不能做的是使它成为一个纯函数/值:

pureCardIndex :: Int
pureCardIndex = ioToPure (getRandomR (0,51)) -- NOT POSSIBLE
Run Code Online (Sandbox Code Playgroud)

因为没有(道德)功能ioToPure.纯函数必须始终返回相同的输出对于相同的输入,而这恰恰不是你想有一个随机数函数做什么.所以我们必须使用IO它.一旦你使用IO随机生成的东西,任何依赖于随机数的东西也必须在IO.

人们将很快开始解释monad理论和所有这些,这是好事,我只是建议耐心地接近它,在进入理论方面之前习惯这些模式.

  • @ftor这不适合使用`unsafePerformIO`,我想大多数社区都会同意我的看法.当我们在haskell工作时,我们对任何函数所期望的第一件事就是引用透明度,这就是让我们心爱的自由来进行等同理性和重构而不用太多考虑.当重新封装违反rt时,`unsafePerformIO`是合适的,因此接口保持纯净. (8认同)
  • @ftor在纯函数式编程语言中,如果是`rand :: Integer - > Integer`,编译器有权将x + x中的x = rand 6作为`rand 6 + rand 6`.如果`rand 6`是骰子的结果,那不是一个合理的重写:例如,前者永远不会是7.调试此问题很容易导致一个疯狂,因为问题不在代码中,而是由编译器引入.这里的编译器没有错,因为它依赖于程序员保证的谎言`rand :: Integer - > Integer` - 这是真正的问题. (6认同)
  • @ftor`unsafePerformIO`适用于具有纯函数但无法向类型系统证明它的情况.调用一个你知道纯粹的函数时,FFI就是一个很好的例子.随机数生成绝对有效,因此应在"IO"内完成. (3认同)