use*_*080 0 random haskell integer
我想使用库System.Random.MWC生成范围(0,30)中的随机整数.我可以使用库System.Random来做到这一点:
import System.Environment
import System.IO.Unsafe
import System.Random
p :: Integer -> Integer
p n = unsafePerformIO (getStdRandom (randomR (0 , n)))
main :: IO()
main = do
print $! (p 30)}
Run Code Online (Sandbox Code Playgroud)
但我对System.Random.MWC感到困惑.
首先,你不应该使用unsafePerformIO.生成随机数是具有副作用的操作,因此p :: Integer -> Integer对于Integer在0给定数量的范围内生成随机的函数不是合适的类型.
以下是如何正确使用System.Random:
import System.Random
p :: Integer -> IO Integer
p n = randomRIO (0 , n)
main :: IO ()
main = do
x <- p 30
print x
Run Code Online (Sandbox Code Playgroud)
因为mwc-random,没有类型的生成器Integer,但有一个用于Int,可能会给你足够大的范围.这是一个例子:
import System.Random.MWC
p :: Int -> GenIO -> IO Int
p n gen = uniformR (0, n) gen
main :: IO ()
main = do
gen <- createSystemRandom
x <- p 30 gen
print x
Run Code Online (Sandbox Code Playgroud)
在你的评论中,你说如果你在GHCi中做这样的事情,就像这样:
Prelude> import System.Random.MWC
Prelude System.Random.MWC> gen <- createSystemRandom
Prelude System.Random.MWC> uniformR (0, 30) gen
27.823000834177332
Run Code Online (Sandbox Code Playgroud)
然后它看起来好像uniformR在生成浮点数,而不是整数.这是由于在Haskell中应用的重载数值类型的"默认",Haskell是Haskell语言的一个陌生和棘手的角落,可能有些令人困惑.类型uniformR是:
uniformR :: (Control.Monad.Primitive.PrimMonad m, Variate a) =>
(a, a) -> Gen (Control.Monad.Primitive.PrimState m) -> m a
Run Code Online (Sandbox Code Playgroud)
在GHCi上下文中,PrimMonad将是IO,因此您可以将类型视为更简单:
uniformR :: Variate a => (a, a) -> GenIO -> IO a
Run Code Online (Sandbox Code Playgroud)
因此结果类型可以是类的IO a任何实例Variate.所述Variate类具有在所定义的各种实例mwc-random包.当你在GHCi中键入它时,没有类型签名或上下文会限制a.那么GHC应该选择多少选项中的哪一个?这就是违约所规定的.Integer那么,Haskell中的标准默认顺序就是Double.没有实例Variate Integer,因此Variate Double选择了实例.如果两个实例都不存在,则会报告类型错误.您始终可以通过提供类型注释来覆盖默认值.所以在这里,你可以做到
Prelude System.Random.MWC> uniformR (0, 30) gen :: IO Int
25
Run Code Online (Sandbox Code Playgroud)
明确指出你想要一个Int,而不是一个Double.