packages feed

random-source 0.3.0.8 → 0.3.0.10

raw patch · 5 files changed

+129/−264 lines, 5 filesdep ~basedep ~mtldep ~random

Dependency ranges changed: base, mtl, random

Files

random-source.cabal view
@@ -1,8 +1,8 @@ name:                   random-source-version:                0.3.0.8+version:                0.3.0.10 stability:              provisional -cabal-version:          >= 1.6+cabal-version:          >= 1.10 build-type:             Simple  author:                 James Cook <mokus@deepbondi.net>@@ -48,16 +48,17 @@ Library   ghc-options:          -Wall   hs-source-dirs:       src+  default-language:     Haskell2010   exposed-modules:      Data.Random.Source                         Data.Random.Source.IO-                        Data.Random.Source.PureMT+                        Data.Random.Source.RandomGen                         Data.Random.Source.Std                         Data.Random.Source.StdGen                         Data.Random.Internal.Words                         Data.Random.Internal.Source   other-modules:        Data.Random.Source.Internal.Prim                         Data.Random.Source.Internal.TH-  +   if impl(ghc >= 6.10)     -- mwc-random depends on vector, which doesn't build on GHC < 6.10.     -- I considered breaking this module out into another package, but I@@ -68,21 +69,21 @@     -- this cabal file is hardly any additional effort.     exposed-modules:    Data.Random.Source.MWC     build-depends:      mwc-random-    +   if flag(mtl2)     build-depends:      mtl == 2.*     cpp-options:        -DMTL2   else     build-depends:      mtl == 1.*-  +   if flag(base4)     build-depends:      base >= 4 && <5, syb   else     build-depends:      base >= 3 && <4-  +   build-depends:        flexible-defaults >= 0.0.0.2,                         mersenne-random-pure64,-                        random,+                        random >= 1.2.0,                         stateref >= 0.3 && < 0.4,                         template-haskell,                         th-extras,
src/Data/Random/Source.hs view
@@ -11,7 +11,7 @@         , getRandomDouble         , getRandomNByteInteger         )-    +     , RandomSource         ( getRandomWord8From         , getRandomWord16From@@ -20,7 +20,7 @@         , getRandomDoubleFrom         , getRandomNByteIntegerFrom         )-    +     , monadRandom, randomSource     ) where @@ -30,7 +30,7 @@ import Data.Random.Source.Internal.TH  $(randomSource-    [d| +    [d|         instance Monad m => RandomSource m (m Word8) where             getRandomWord8From = id      |])
− src/Data/Random/Source/PureMT.hs
@@ -1,162 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TemplateHaskell, GADTs #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}---- |This module provides functions useful for implementing new 'MonadRandom'--- and 'RandomSource' instances for state-abstractions containing 'PureMT'--- values (the pure pseudorandom generator provided by the--- mersenne-random-pure64 package), as well as instances for some common--- cases.--- --- A 'PureMT' generator is immutable, so 'PureMT' by itself cannot be a --- 'RandomSource' (if it were, it would always give the same \"random\"--- values).  Some form of mutable state must be used, such as an 'IORef',--- 'State' monad, etc..  A few default instances are provided by this module--- along with a more-general function ('getRandomPrimFromMTRef') usable as--- an implementation for new cases users might need.-module Data.Random.Source.PureMT -    ( PureMT, newPureMT, pureMT-    -    , getRandomPrimFromMTRef-    ) where--import Control.Monad.State-import Control.Monad.RWS-import qualified Control.Monad.State.Strict as S-import qualified Control.Monad.RWS.Strict as S-import Data.Random.Internal.Source-import Data.Random.Source.Internal.TH-import Data.StateRef-import System.Random.Mersenne.Pure64--{-# INLINE withMTRef #-}-withMTRef :: (Monad m, ModifyRef sr m PureMT) => (PureMT -> (t, PureMT)) -> sr -> m t-withMTRef thing ref = atomicModifyReference ref $ \(!oldMT) -> -    case thing oldMT of (!w, !newMT) -> (newMT, w)--{-# INLINE withMTState #-}-withMTState :: MonadState PureMT m => (PureMT -> (t, PureMT)) -> m t-withMTState thing = do-    !mt <- get-    let (!ws, !newMt) = thing mt-    put newMt-    return ws--#ifndef MTL2--$(monadRandom-    [d| instance MonadRandom (State PureMT) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--$(monadRandom-    [d| instance MonadRandom (S.State PureMT) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--$(monadRandom-    [d| instance Monoid w => MonadRandom (RWS r w PureMT) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--$(monadRandom-    [d| instance Monoid w => MonadRandom (S.RWS r w PureMT) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--#endif--$(randomSource-    [d| instance (Monad m1, ModifyRef (Ref m2 PureMT) m1 PureMT) => RandomSource m1 (Ref m2 PureMT) where-            getRandomWord64From = withMTRef randomWord64-            getRandomDoubleFrom = withMTRef randomDouble-    |])--$(monadRandom-    [d| instance Monad m => MonadRandom (StateT PureMT m) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--$(monadRandom-    [d| instance Monad m => MonadRandom (S.StateT PureMT m) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--$(monadRandom-    [d| instance (Monad m, Monoid w) => MonadRandom (RWST r w PureMT m) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--$(monadRandom-    [d| instance (Monad m, Monoid w) => MonadRandom (S.RWST r w PureMT m) where-            getRandomWord64 = withMTState randomWord64-            getRandomDouble = withMTState randomDouble-     |])--$(randomSource-    [d| instance (MonadIO m) => RandomSource m (IORef PureMT) where-            getRandomWord64From = withMTRef randomWord64-            getRandomDoubleFrom = withMTRef randomDouble-     |])--$(randomSource-    [d| instance (Monad m, ModifyRef (STRef s PureMT) m PureMT) => RandomSource m (STRef s PureMT) where-            getRandomWord64From = withMTRef randomWord64-            getRandomDoubleFrom = withMTRef randomDouble-     |])---- Note that this instance is probably a Bad Idea.  STM allows random variables--- to interact in spooky quantum-esque ways - One transaction can 'retry' until--- it gets a \"random\" answer it likes, which causes it to selectively consume --- entropy, biasing the supply from which other random variables will draw.--- instance (Monad m, ModifyRef (TVar PureMT) m PureMT) => RandomSource m (TVar PureMT) where---     {-# SPECIALIZE instance RandomSource IO  (TVar PureMT) #-}---     {-# SPECIALIZE instance RandomSource STM (TVar PureMT) #-}---     getRandomPrimFrom = getRandomPrimFromMTRef----- |Given a mutable reference to a 'PureMT' generator, we can implement--- 'RandomSource' for it in any monad in which the reference can be modified.--- --- Typically this would be used to define a new 'RandomSource' instance for--- some new reference type or new monad in which an existing reference type--- can be modified atomically.  As an example, the following instance could--- be used to describe how 'IORef' 'PureMT' can be a 'RandomSource' in the--- 'IO' monad:--- --- > instance RandomSource IO (IORef PureMT) where--- >     supportedPrimsFrom _ _ = True--- >     getSupportedRandomPrimFrom = getRandomPrimFromMTRef--- --- (note that there is actually a more general instance declared already--- covering this as a a special case, so there's no need to repeat this--- declaration anywhere)--- --- Example usage (using some functions from "Data.Random" in the random-fu --- package):--- --- > main = do--- >     src <- newIORef (pureMT 1234)          -- OR: newPureMT >>= newIORef--- >     x <- runRVar (uniform 0 100) src :: IO Double--- >     print x-getRandomPrimFromMTRef :: ModifyRef sr m PureMT => sr -> Prim a -> m a-getRandomPrimFromMTRef ref-    = atomicModifyReference' ref -    . runState -    . getRandomPrim--atomicModifyReference' :: ModifyRef sr m a => sr -> (a -> (b, a)) -> m b-atomicModifyReference' ref getR =-    atomicModifyReference ref (swap' . getR)-        where swap' (!a,!b) = (b,a)
+ src/Data/Random/Source/RandomGen.hs view
@@ -0,0 +1,106 @@++{-# LANGUAGE+    CPP,+    MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GADTs,+    BangPatterns, RankNTypes,+    ScopedTypeVariables+  #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-- |This module provides functions useful for implementing new 'MonadRandom'+-- and 'RandomSource' instances for state-abstractions containing over 'RandomGen'+-- instance (the type class for pseudorandom generators provided by the System.Random+-- module in the \"random\" package), as well as instances for some common+-- cases.+module Data.Random.Source.RandomGen+    ( getRandomPrimFromRandomGenRef+    , getRandomPrimFromRandomGenState+    ) where++import Data.Random.Internal.Source+import System.Random+import Control.Monad.State+import Control.Monad.RWS+import qualified Control.Monad.State.Strict as S+import qualified Control.Monad.RWS.Strict as S+import Data.StateRef+import Data.Word+++instance (Monad m1, RandomGen g, ModifyRef (Ref m2 g) m1 g) => RandomSource m1 (Ref m2 g) where+    getRandomPrimFrom = getRandomPrimFromRandomGenRef++instance (Monad m, RandomGen g, ModifyRef (IORef g) m g) => RandomSource m (IORef g) where+    {-# SPECIALIZE instance RandomSource IO (IORef StdGen) #-}+    getRandomPrimFrom = getRandomPrimFromRandomGenRef++-- |Given a mutable reference to a 'RandomGen' generator, we can make a+-- 'RandomSource' usable in any monad in which the reference can be modified.+getRandomPrimFromRandomGenRef :: (Monad m, ModifyRef sr m g, RandomGen g) =>+                                  sr -> Prim a -> m a+getRandomPrimFromRandomGenRef ref+    = atomicModifyReference' ref+    . runState+    . getRandomPrimFromRandomGenState++atomicModifyReference' :: ModifyRef sr m a => sr -> (a -> (b, a)) -> m b+atomicModifyReference' ref getR =+    atomicModifyReference ref (swap' . getR)+        where swap' (!a,!b) = (b,a)+++-- |Similarly, @getRandomWordFromRandomGenState x@ can be used in any \"state\"+-- monad in the mtl sense whose state is a 'RandomGen' generator.+-- Additionally, the standard mtl state monads have 'MonadRandom' instances+-- which do precisely that, allowing an easy conversion of 'RVar's and+-- other 'Distribution' instances to \"pure\" random variables.+getRandomPrimFromRandomGenState :: forall g m a. (RandomGen g, MonadState g m) => Prim a -> m a+getRandomPrimFromRandomGenState = genPrim+    where+        {-# INLINE genPrim #-}+        genPrim :: forall t. Prim t -> m t+        genPrim PrimWord8            = getThing (randomR (0, 0xff))                (fromIntegral :: Int -> Word8)+        genPrim PrimWord16           = getThing (randomR (0, 0xffff))              (fromIntegral :: Int -> Word16)+        genPrim PrimWord32           = getThing (randomR (0, 0xffffffff))          (fromInteger)+        genPrim PrimWord64           = getThing (randomR (0, 0xffffffffffffffff))  (fromInteger)+        genPrim PrimDouble           = getThing (randomR (0, 0x000fffffffffffff))  (flip encodeFloat (-52))+          {- not using the Random Double instance for 2 reasons.  1st, it only generates 32 bits of entropy, when+             a [0,1) Double has room for 52.  Second, it appears there's a bug where it can actually generate a+             negative number in the case where randomIvalInteger returns minBound::Int32. -}+--        genPrim PrimDouble = getThing (randomR (0, 1.0))  (id)+        genPrim (PrimNByteInteger n) = getThing (randomR (0, iterate (*256) 1 !! n)) id++        {-# INLINE getThing #-}+        getThing :: forall b t. (g -> (b, g)) -> (b -> t) -> m t+        getThing thing f = do+            !oldGen <- get+            case thing oldGen of+                (!i,!newGen) -> do+                    put newGen+                    return (f $! i)++#ifndef MTL2+instance RandomGen g => MonadRandom (State g) where+    getRandomPrim = getRandomPrimFromRandomGenState++instance RandomGen g => MonadRandom (S.State g) where+    getRandomPrim = getRandomPrimFromRandomGenState++instance (RandomGen g, Monoid w) => MonadRandom (RWS r w g) where+    getRandomPrim = getRandomPrimFromRandomGenState++instance (RandomGen g, Monoid w) => MonadRandom (S.RWS r w g) where+    getRandomPrim = getRandomPrimFromRandomGenState+#endif++instance (RandomGen g, Monad m) => MonadRandom (StateT g m) where+    getRandomPrim = getRandomPrimFromRandomGenState++instance (RandomGen g, Monad m) => MonadRandom (S.StateT g m) where+    getRandomPrim = getRandomPrimFromRandomGenState++instance (RandomGen g, Monad m, Monoid w) => MonadRandom (RWST r w g m) where+    getRandomPrim = getRandomPrimFromRandomGenState++instance (RandomGen g, Monad m, Monoid w) => MonadRandom (S.RWST r w g m) where+    getRandomPrim = getRandomPrimFromRandomGenState
src/Data/Random/Source/StdGen.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE-    CPP,     MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GADTs,     BangPatterns, RankNTypes,     ScopedTypeVariables@@ -15,33 +14,23 @@     ( StdGen     , mkStdGen     , newStdGen-    +     , getRandomPrimFromStdGenIO-    , getRandomPrimFromRandomGenRef-    , getRandomPrimFromRandomGenState+    , RandomGen.getRandomPrimFromRandomGenRef+    , RandomGen.getRandomPrimFromRandomGenState     ) where  import Data.Random.Internal.Source+import qualified Data.Random.Source.RandomGen as RandomGen import System.Random import Control.Monad.State-import Control.Monad.RWS import qualified Control.Monad.ST.Strict as S-import qualified Control.Monad.State.Strict as S-import qualified Control.Monad.RWS.Strict as S import Data.StateRef-import Data.Word  -instance (Monad m1, ModifyRef (Ref m2 StdGen) m1 StdGen) => RandomSource m1 (Ref m2 StdGen) where-    getRandomPrimFrom = getRandomPrimFromRandomGenRef--instance (Monad m, ModifyRef (IORef   StdGen) m StdGen) => RandomSource m (IORef   StdGen) where-    {-# SPECIALIZE instance RandomSource IO (IORef StdGen) #-}-    getRandomPrimFrom = getRandomPrimFromRandomGenRef- -- Note that this instance is probably a Bad Idea.  STM allows random variables -- to interact in spooky quantum-esque ways - One transaction can 'retry' until--- it gets a \"random\" answer it likes, which causes it to selectively consume +-- it gets a \"random\" answer it likes, which causes it to selectively consume -- entropy, biasing the supply from which other random variables will draw. -- instance (Monad m, ModifyRef (TVar    StdGen) m StdGen) => RandomSource m (TVar    StdGen) where --     {-# SPECIALIZE instance RandomSource IO  (TVar StdGen) #-}@@ -52,91 +41,22 @@ instance (Monad m, ModifyRef (STRef s StdGen) m StdGen) => RandomSource m (STRef s StdGen) where     {-# SPECIALIZE instance RandomSource (ST s) (STRef s StdGen) #-}     {-# SPECIALIZE instance RandomSource (S.ST s) (STRef s StdGen) #-}-    getRandomPrimFrom = getRandomPrimFromRandomGenRef+    getRandomPrimFrom = RandomGen.getRandomPrimFromRandomGenRef  getRandomPrimFromStdGenIO :: Prim a -> IO a-getRandomPrimFromStdGenIO +getRandomPrimFromStdGenIO     = getStdRandom     . runState     . getRandomPrim --- |Given a mutable reference to a 'RandomGen' generator, we can make a--- 'RandomSource' usable in any monad in which the reference can be modified.--- --- See "Data.Random.Source.PureMT".'getRandomPrimFromMTRef' for more detailed--- usage hints - this function serves exactly the same purpose except for a--- 'StdGen' generator instead of a 'PureMT' generator.-getRandomPrimFromRandomGenRef :: (Monad m, ModifyRef sr m g, RandomGen g) =>-                                  sr -> Prim a -> m a-getRandomPrimFromRandomGenRef ref -    = atomicModifyReference' ref -    . runState -    . getRandomPrimFromRandomGenState--atomicModifyReference' :: ModifyRef sr m a => sr -> (a -> (b, a)) -> m b-atomicModifyReference' ref getR =-    atomicModifyReference ref (swap' . getR)-        where swap' (!a,!b) = (b,a)-- -- |Similarly, @getRandomWordFromRandomGenState x@ can be used in any \"state\" -- monad in the mtl sense whose state is a 'RandomGen' generator. -- Additionally, the standard mtl state monads have 'MonadRandom' instances -- which do precisely that, allowing an easy conversion of 'RVar's and -- other 'Distribution' instances to \"pure\" random variables.--- +-- -- Again, see "Data.Random.Source.PureMT".'getRandomPrimFromMTState' for more--- detailed usage hints - this function serves exactly the same purpose except +-- detailed usage hints - this function serves exactly the same purpose except -- for a 'StdGen' generator instead of a 'PureMT' generator.-{-# SPECIALIZE getRandomPrimFromRandomGenState :: Prim a -> State StdGen a #-}-{-# SPECIALIZE getRandomPrimFromRandomGenState :: Monad m => Prim a -> StateT StdGen m a #-}-getRandomPrimFromRandomGenState :: forall g m a. (RandomGen g, MonadState g m) => Prim a -> m a-getRandomPrimFromRandomGenState = genPrim-    where -        {-# INLINE genPrim #-}-        genPrim :: forall t. Prim t -> m t-        genPrim PrimWord8            = getThing (randomR (0, 0xff))                (fromIntegral :: Int -> Word8)-        genPrim PrimWord16           = getThing (randomR (0, 0xffff))              (fromIntegral :: Int -> Word16)-        genPrim PrimWord32           = getThing (randomR (0, 0xffffffff))          (fromInteger)-        genPrim PrimWord64           = getThing (randomR (0, 0xffffffffffffffff))  (fromInteger)-        genPrim PrimDouble           = getThing (randomR (0, 0x000fffffffffffff))  (flip encodeFloat (-52))-          {- not using the Random Double instance for 2 reasons.  1st, it only generates 32 bits of entropy, when -             a [0,1) Double has room for 52.  Second, it appears there's a bug where it can actually generate a -             negative number in the case where randomIvalInteger returns minBound::Int32. -}---        genPrim PrimDouble = getThing (randomR (0, 1.0))  (id)-        genPrim (PrimNByteInteger n) = getThing (randomR (0, iterate (*256) 1 !! n)) id-        -        {-# INLINE getThing #-}-        getThing :: forall b t. (g -> (b, g)) -> (b -> t) -> m t-        getThing thing f = do-            !oldGen <- get-            case thing oldGen of-                (!i,!newGen) -> do-                    put newGen-                    return (f $! i)--#ifndef MTL2-instance MonadRandom (State StdGen) where-    getRandomPrim = getRandomPrimFromRandomGenState--instance MonadRandom (S.State StdGen) where-    getRandomPrim = getRandomPrimFromRandomGenState--instance Monoid w => MonadRandom (RWS r w StdGen) where-    getRandomPrim = getRandomPrimFromRandomGenState--instance Monoid w => MonadRandom (S.RWS r w StdGen) where-    getRandomPrim = getRandomPrimFromRandomGenState-#endif--instance Monad m => MonadRandom (StateT StdGen m) where-    getRandomPrim = getRandomPrimFromRandomGenState--instance Monad m => MonadRandom (S.StateT StdGen m) where-    getRandomPrim = getRandomPrimFromRandomGenState--instance (Monad m, Monoid w) => MonadRandom (RWST r w StdGen m) where-    getRandomPrim = getRandomPrimFromRandomGenState--instance (Monad m, Monoid w) => MonadRandom (S.RWST r w StdGen m) where-    getRandomPrim = getRandomPrimFromRandomGenState+{-# SPECIALIZE RandomGen.getRandomPrimFromRandomGenState :: Prim a -> State StdGen a #-}+{-# SPECIALIZE RandomGen.getRandomPrimFromRandomGenState :: Monad m => Prim a -> StateT StdGen m a #-}