2014-09-17 2 views
3

Я хочу, чтобы иметь возможность использовать MWC random number generator со случайным fu, и поэтому необходимо реализовать экземпляр MonadRandom. Моя попытка рассмотреть Reader (Gen (PrimState m)) v a MonadRandom v. Однако, следующее терпит неудачу:Запись экземпляра MonadRandom для MWC (Haskell)

$(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)))’ 

Что я делаю неправильно?

+3

Проблема заключается именно в том, что компилятор сказал вам это: вы не можете иметь типовые семейные приложения в экземпляре. Самый простой способ избавиться от семейства типов в экземпляре * head * - просто поместить его в * context *: 'instance (PrimMonad m, s ~ PrimState m) => MonadRandom (Reader (MWC.Gen s)) '(при условии, что фактический код в противном случае правильный, и, конечно, нет других проблем). Другое решение заменяет «PrimState m» на то, что он представляет, а именно один раз для «IO» и один для «ST s». – user2407038

ответ

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 
0

Я думаю, что вы хотели было на самом деле:

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

Вы, вероятно, также необходимо заменить MWC.uniform с

lift . MWC.uniform 
+0

Я думаю, что вы имели в виду (ReaderT (MWC.Gen s) m)? – idontgetoutmuch

+0

Моя ошибка: я собрал два ответа. – idontgetoutmuch

Смежные вопросы