生成具有恒定堆栈空间的随机向量

时间:2013-11-13 05:59:07

标签: haskell stack-overflow monads lazy-evaluation

我正在使用Don Stewart的包System.Random.Mersenne.Pure64Control.Monad.Mersenne.Random,这些包通常非常快,而且supposed to help avoid common errors就像使用非严格状态monad一样。

尽管如此,我设法编写了一些代码,这些代码会导致中等大型向量的堆栈溢出。

import qualified Data.Vector.Unboxed as U
import Data.Int
import System.Random.Mersenne.Pure64
import Control.Monad.Mersenne.Random

main = do
    let dim = 1000000
        y = evalRandom (U.replicateM dim getInt64) (pureMT 13) :: U.Vector Int64
    putStr $ (show $ U.head y)

我猜这一定是由于Vector的replicateM实现中的懒惰,但由于它是使用streams实现的,因此很难看到。

我如何编写使用常量堆栈空间来对大型矢量进行采样的代码?

1 个答案:

答案 0 :(得分:6)

monad-mersenne-random(没有看到核心的iota)没有立即出现明显的错误,但值得注意的是,当使用状态monad时一切正常:

import Control.Monad.State

...

        y      = evalState (U.replicateM dim (state $ \s -> randomInt64 s)) (pureMT 13) :: U.Vector Int64

结果:

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.6.3
$ ghc so.hs -fforce-recomp
[1 of 2] Compiling Control.Monad.Mersenne.Random ( Control/Monad/Mersenne/Random.hs, Control/Monad/Mersenne/Random.o )
[2 of 2] Compiling Main             ( so.hs, so.o )
Linking so ...
$ ./so
-7188968464842378225

编辑:

看两个monad定义(StateTRand),似乎唯一真正的区别在于元组的严格性。所以我尝试使用Control.Monad.State.Strict和啊哈!堆栈溢出返回。所以我猜测埋在Vector的replicateM代码中的内容类似于foldr replicateM中使用的base。这可以解释为什么你不希望序列是严格的。