在算术和逻辑运算中使用从 Haskell 中的全局随机数生成器获得的随机值
Using random values obtained from the global random number generator in Haskell in arithmetic and logic operations
如何在算术和逻辑运算中使用Haskell中全局随机数生成器获得的IO Double
值?网上的大部分教程都侧重于获取随机数,但不知怎么的,我似乎无法用它们做一些有用的事情。
以下代码包含一些函数 test
,其中包含我要执行的一些操作。
{-# LANGUAGE Strict #-}
module RNG where
import System.Random(setStdGen, mkStdGen, randomRIO)
seed_rng :: Int -> IO()
seed_rng seed = (setStdGen (mkStdGen seed))
uniform_float :: IO Double
uniform_float = (randomRIO (0.0, 1.0))
test :: Double -> Double -> IO Double
test a b = let u = (uniform_float)
in if ((<) (return a) u) then ((+) (return b) u) else (return 2.0)
测试函数无法编译,因为没有 Ord (IO Double)
和 Num (IO Double)
的实例。
请注意,我可以通过实现随机数生成器并自己跟踪+传递状态来避免 IO Monad
。但我宁愿学习与 Monads
一起工作,而不是总是试图 运行 远离他们。
在 monadic 上下文中,您可以使用 do
实际 运行 计算:
test :: Double -> Double -> IO Double
test a b = do
u <- uniform_float
if a < u
then return (b + u)
else return 2.0
大意是:用<-
暂时从一个IO Double
中取出一个Double
,然后用[=17=把结果放回IO
里面].
例如,这对两个统一数求和:
sumTwo :: IO Double
sumTwo = do
x <- uniform_float
y <- uniform_float
return (x+y)
有 do
的替代方法,但我建议先学习 do
,因为它相当通用且足够简单。当您更习惯于单子计算、应用程序和仿函数时,您可能还会喜欢紧凑的替代方案,例如 sumTwo = (+) <$> uniform_float <*> uniform_float
.
(>>=)
可用于链接使用 Double
值的第二个单子计算。
test :: Double -> Double -> IO Double
test a b = uniform_float >>= \u -> return (if a < u then b + u else 2.0)
另一种编写上述内容的方法是使用 do 块:
test :: Double -> Double -> IO Double
test a b = do
u <- uniform_float
return (if a < u then b + u else 2.0)
最后,在这种情况下,第二个单子计算只是一个非单子计算,后跟 return
,你甚至不需要 (>>=)
-- fmap
就够了:
test :: Double -> Double -> IO Double
test a b = fmap (\u -> if a < u then b + u else 2.0) uniform_float
如何在算术和逻辑运算中使用Haskell中全局随机数生成器获得的IO Double
值?网上的大部分教程都侧重于获取随机数,但不知怎么的,我似乎无法用它们做一些有用的事情。
以下代码包含一些函数 test
,其中包含我要执行的一些操作。
{-# LANGUAGE Strict #-}
module RNG where
import System.Random(setStdGen, mkStdGen, randomRIO)
seed_rng :: Int -> IO()
seed_rng seed = (setStdGen (mkStdGen seed))
uniform_float :: IO Double
uniform_float = (randomRIO (0.0, 1.0))
test :: Double -> Double -> IO Double
test a b = let u = (uniform_float)
in if ((<) (return a) u) then ((+) (return b) u) else (return 2.0)
测试函数无法编译,因为没有 Ord (IO Double)
和 Num (IO Double)
的实例。
请注意,我可以通过实现随机数生成器并自己跟踪+传递状态来避免 IO Monad
。但我宁愿学习与 Monads
一起工作,而不是总是试图 运行 远离他们。
在 monadic 上下文中,您可以使用 do
实际 运行 计算:
test :: Double -> Double -> IO Double
test a b = do
u <- uniform_float
if a < u
then return (b + u)
else return 2.0
大意是:用<-
暂时从一个IO Double
中取出一个Double
,然后用[=17=把结果放回IO
里面].
例如,这对两个统一数求和:
sumTwo :: IO Double
sumTwo = do
x <- uniform_float
y <- uniform_float
return (x+y)
有 do
的替代方法,但我建议先学习 do
,因为它相当通用且足够简单。当您更习惯于单子计算、应用程序和仿函数时,您可能还会喜欢紧凑的替代方案,例如 sumTwo = (+) <$> uniform_float <*> uniform_float
.
(>>=)
可用于链接使用 Double
值的第二个单子计算。
test :: Double -> Double -> IO Double
test a b = uniform_float >>= \u -> return (if a < u then b + u else 2.0)
另一种编写上述内容的方法是使用 do 块:
test :: Double -> Double -> IO Double
test a b = do
u <- uniform_float
return (if a < u then b + u else 2.0)
最后,在这种情况下,第二个单子计算只是一个非单子计算,后跟 return
,你甚至不需要 (>>=)
-- fmap
就够了:
test :: Double -> Double -> IO Double
test a b = fmap (\u -> if a < u then b + u else 2.0) uniform_float