我想用System.Random.MWC.Monad的Rand monad生成无限的数字流。如果这个monad有一个MonadFix实例就好了,或者像这样的实例:
instance (PrimMonad m) => MonadFix m where
...然后可以这样写:
runWithSystemRandom (mfix (\ xs -> uniform >>= \x -> return (x:xs)))不过,没有一个。
我正在使用MonadFix docs,但我看不到实现此实例的明显方法。
发布于 2011-03-22 02:34:59
一个问题:你希望如何生成你的初始种子?
问题是,MWS是建立在“原始”包上的,它只抽象IO和严格(Control.Monad.ST.ST )。它也不抽象惰性(Control.Monad.ST.Lazy.ST s)。
也许可以为"primitive“创建实例来覆盖lazy ST,然后MWS就可以是惰性的了。
更新:我可以通过使用strictToLazyST使用Control.Monad.ST.Lazy来实现这一点:
module Main where
import Control.Monad(replicateM)
import qualified Control.Monad.ST as S
import qualified Control.Monad.ST.Lazy as L
import qualified System.Random.MWC as A
foo :: Int -> L.ST s [Int]
foo i = do rest <- foo $! succ i
return (i:rest)
splam :: A.Gen s -> S.ST s Int
splam = A.uniformR (0,100)
getS :: Int -> S.ST s [Int]
getS n = do gen <- A.create
replicateM n (splam gen)
getL :: Int -> L.ST s [Int]
getL n = do gen <- createLazy
replicateM n (L.strictToLazyST (splam gen))
createLazy :: L.ST s (A.Gen s)
createLazy = L.strictToLazyST A.create
makeLots :: A.Gen s -> L.ST s [Int]
makeLots gen = do x <- L.strictToLazyST (A.uniformR (0,100) gen)
rest <- makeLots gen
return (x:rest)
main = do
print (S.runST (getS 8))
print (L.runST (getL 8))
let inf = L.runST (foo 0) :: [Int]
print (take 10 inf)
let inf3 = L.runST (createLazy >>= makeLots) :: [Int]
print (take 10 inf3)发布于 2011-03-20 09:50:15
您可以编写MonadFix实例。但是,该代码不会生成不同的随机数的无限流。mfix的参数是一个只调用uniform一次的函数。当代码运行时,它将恰好调用uniform一次,并创建一个包含结果的无限列表。
您可以尝试等效的IO代码,看看会发生什么:
import System.Random
import Control.Monad.Fix
main = print . take 10 =<< mfix (\xs -> randomIO >>= (\x -> return (x : xs :: [Int])))您似乎希望使用有状态随机数生成器,并且希望运行生成器并懒惰地收集其结果。如果不小心使用unsafePerformIO,这是不可能的。除非您需要快速生成许多随机数,否则可以使用纯RNG函数,如randomRs。
发布于 2014-09-14 15:32:52
(这将更适合作为散热器的答案的注释,但它有点太长了。)
MonadFix实例必须遵守several laws。其中一个正在收缩/变粗。
mfix (\x -> a >>= \y -> f x y) = a >>= \y -> mfix (\x -> f x y)这条法律允许将表达式重写为
mfix (\xs -> uniform >>= \x -> return (x:xs))
= uniform >>= \x -> mfix (\xs -> return (x:xs))
= uniform >>= \x -> mfix (return . (x :))使用另一个定律purity mfix (return . h) = return (fix h),我们可以进一步简化为
= uniform >>= \x -> return (fix (x :))并使用标准的单元律并将fix (x :)重写为repeat x
= liftM (\x -> fix (x :)) uniform
= liftM repeat uniform因此,结果确实是一次调用uniform,然后无限地重复单个值。
https://stackoverflow.com/questions/5365292
复制相似问题