haskell将IO Int转换为Int System.Random.MWC

haskell将IO Int转换为Int System.Random.MWC,haskell,io,Haskell,Io,我想使用unsafePerformIO将System.Random.MWC中的IO Int转换为Int。它在ghci中起作用: Prelude System.Random.MWC System.IO.Unsafe> let p = unsafePerformIO(uniformR (0, 30) gen :: IO Int) Prelude System.Random.MWC System.IO.Unsafe> p 11 Prelude System.Random.MWC Sy

我想使用
unsafePerformIO
System.Random.MWC
中的
IO Int
转换为
Int
。它在ghci中起作用:

Prelude System.Random.MWC System.IO.Unsafe> let p = unsafePerformIO(uniformR (0, 30) gen :: IO Int)

Prelude System.Random.MWC System.IO.Unsafe> p

11

Prelude System.Random.MWC System.IO.Unsafe> :t p

p :: Int
但是在GHC中

import System.Random.MWC
import System.IO.Unsafe  

main :: IO()
main = do
        gen <-createSystemRandom
        print $! s 30 gen

s :: Int-> GenIO -> Int
s !k g = unsafePerformIO(uniformR (0, k - 1) g)

这里真的不需要
unsafePerformIO
。只需将
s
的类型更改为返回
IO Int
,然后使用do表示法或bind操作符将结果馈送到
print

s :: Int -> GenIO -> IO Int
s k g = uniformR (0, k - 1) g

main :: IO ()
main = do
    gen <- createSystemRandom
    x <- s 30 gen
    print x
s::Int->GenIO->IO Int
skg=uniformR(0,k-1)g
main::IO()
main=do

gen这里真的不需要
unsafePerformIO
。只需将
s
的类型更改为返回
IO Int
,然后使用do表示法或bind操作符将结果馈送到
print

s :: Int -> GenIO -> IO Int
s k g = uniformR (0, k - 1) g

main :: IO ()
main = do
    gen <- createSystemRandom
    x <- s 30 gen
    print x
s::Int->GenIO->IO Int
skg=uniformR(0,k-1)g
main::IO()
main=do

gen为什么会认为这样做是个好主意?有一个很好的理由,这会产生
IO Int
而不是
Int
:它不是一个实际的整数值,只是一个获得这样一个值的“配方”。如果ghci实际上只是将其作为类型为
Int
的“隐藏”值来实现,并且因此您能够使用
unsafeccerce
获得一个随机数,那么这比其他任何东西都要幸运。通常的回答是“它被称为不安全是有原因的”,但人们常常发现,明智地使用它并没有太大的负面影响。然而,这并不是其中之一-
mwc random
是一个非常积极优化的库,它在调用时解包并内联一整批函数体。最终的结果是,它为
不安全*
呼叫提供了一个敌对环境。啊,对不起,我误读了,您实际上没有使用
不安全强制
,而只是使用
不安全性能
——这就没那么错了。如果您需要将其作为随机(但请确定!)算法的一部分,那么在
unsafePerformIO
的帮助下,将其作为纯函数应该是可以的,但只能围绕整个算法进行,因为对于单个随机数(显然不确定!),这没有意义。然而,最终的结果是,正如J.Abrahamson所说,这是合理的,也不应该导致内联问题可能发生的任何问题。为什么会认为这样做是一个好主意?有一个很好的理由,这会产生
IO Int
而不是
Int
:它不是一个实际的整数值,只是一个获得这样一个值的“配方”。如果ghci实际上只是将其作为类型为
Int
的“隐藏”值来实现,并且因此您能够使用
unsafeccerce
获得一个随机数,那么这比其他任何东西都要幸运。通常的回答是“它被称为不安全是有原因的”,但人们常常发现,明智地使用它并没有太大的负面影响。然而,这并不是其中之一-
mwc random
是一个非常积极优化的库,它在调用时解包并内联一整批函数体。最终的结果是,它为
不安全*
呼叫提供了一个敌对环境。啊,对不起,我误读了,您实际上没有使用
不安全强制
,而只是使用
不安全性能
——这就没那么错了。如果您需要将其作为随机(但请确定!)算法的一部分,那么在
unsafePerformIO
的帮助下,将其作为纯函数应该是可以的,但只能围绕整个算法进行,因为对于单个随机数(显然不确定!),这没有意义。然而,最终结果是合理的,也不应该像J.Abrahamson所说的那样,因为内联问题而导致任何可能发生的问题。我需要在我的程序中得到结果。实际上,我想随机选择一个置换(Fisher-Yates算法)@user2746080:在这种情况下,您应该修改您的代码,使其也在
IO
中工作,并使用do符号编写您的洗牌函数。然后您可以使用System.Random my Shuffle函数获得结果:Shuffle::[Integer]->Integer->[Integer]Shuffle xs 1=xs Shuffle!xs!k=shuffle(sswap(unsafePerformIO(getStdRandom(randomR(0,k-1)))kxs)(k-1),它调用sswap函数:sswap::Integer->Integer->[Integer]->[Integer]sswap!我Jxs=genericTake i xs++[xs!!(from积分j)]++(genericTake(j-i-1)$genericDrop(i+1)xs)+[xs!!(from积分i)]+++genericDrop(j+1)xs它工作正常,但我不知道用do符号来写它。感谢您的帮助。@user2746080也许您应该仔细阅读do符号和单子:不,它“工作不好”。幸运的情况是它能在你的情况下做你想做的。我需要在我的程序中得到结果。实际上,我想随机选择一个置换(Fisher-Yates算法)@user2746080:在这种情况下,您应该修改您的代码,使其也在
IO
中工作,并使用do符号编写您的洗牌函数。然后您可以使用System.Random my Shuffle函数获得结果:Shuffle::[Integer]->Integer->[Integer]Shuffle xs 1=xs Shuffle!xs!k=shuffle(sswap(unsafePerformIO(getStdRandom(randomR(0,k-1)))kxs)(k-1),它调用sswap函数:sswap::Integer->Integer->[Integer]->[Integer]sswap!我Jxs=genericTake i xs++[xs!!(from积分j)]++(genericTake(j-i-1)$genericDrop(i+1)xs)+[xs!!(from积分i)]+++genericDrop(j+1)xs它工作正常,但我不知道用do符号来写它。感谢您的帮助。@user2746080也许您应该仔细阅读do符号和单子:不,它“工作不好”。幸运的是,在你的情况下,它能做你想做的事情。
main = do
    gen <- createSystemRandom
    print =<< s 30 gen
main = print =<< s 30 =<< createSystemRandom