为MWC编写MonadRandom实例(Haskell)

时间:2014-09-17 09:07:30

标签: haskell monads

我希望能够将MWC random number generator与random-fu一起使用,因此需要实现MonadRandom的实例。我的尝试是考虑Reader (Gen (PrimState m)) v a MonadRandom v。但是,以下失败:

$(monadRandom [d|
  instance (PrimMonad m) => MonadRandom (Reader (MWC.Gen (PrimState m))) where
    getRandomWord16 = ask >>= MWC.uniform
    getRandomWord32 = ask >>= MWC.uniform
    getRandomWord64 = ask >>= MWC.uniform
  |])

错误:

Illegal type synonym family application in instance:
  Reader (MWC.Gen (PrimState m_ahwD))
In the instance declaration for
  ‘MonadRandom (Reader (MWC.Gen (PrimState m_ahwD)))’

我做错了什么?

2 个答案:

答案 0 :(得分:1)

以其他贡献者已经说过的为基础

{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE GADTs             #-}
{-# LANGUAGE FlexibleInstances #-}

import Data.Random
import Data.Random.Source
import qualified System.Random.MWC as MWC
import Control.Monad.Reader
import Control.Monad.Primitive

$(monadRandom [d|
  instance (PrimMonad m, s ~ PrimState m) => MonadRandom (ReaderT (MWC.Gen s) m) where
    getRandomWord16 = ask >>= lift . MWC.uniform
    getRandomWord32 = ask >>= lift . MWC.uniform
    getRandomWord64 = ask >>= lift . MWC.uniform
  |])

testUniform :: MonadRandom m => Int -> m [Double]
testUniform n = replicateM (fromIntegral n) (sample stdUniform)

n :: Int
n = 10^7

main :: IO ()
main = do
    seed <- MWC.create
    xs <- runReaderT (testUniform n) seed
    print (sum xs / fromIntegral n)

但效果不是很好

./RandomFuMWC +RTS -s
0.5000432391067587
   3,286,220,896 bytes allocated in the heap
   2,427,475,880 bytes copied during GC
     600,186,048 bytes maximum residency (12 sample(s))
     100,510,656 bytes maximum slop
            1249 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0      5942 colls,     0 par    1.06s    1.13s     0.0002s    0.0013s
  Gen  1        12 colls,     0 par    0.82s    1.23s     0.1024s    0.5787s

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    1.47s  (  1.39s elapsed)
  GC      time    1.87s  (  2.36s elapsed)
  EXIT    time    0.01s  (  0.09s elapsed)
  Total   time    3.35s  (  3.84s elapsed)

  %GC     time      56.0%  (61.3% elapsed)

  Alloc rate    2,242,365,923 bytes per MUT second

  Productivity  44.0% of total user, 38.3% of total elapsed

答案 1 :(得分:0)

我认为你想要的实际上是:

(ReaderT (MWC.Gen (PrimState m)) m)

您可能还需要将MWC.uniform替换为

lift . MWC.uniform