33{-# LANGUAGE FunctionalDependencies #-}
44{-# LANGUAGE GeneralizedNewtypeDeriving #-}
55{-# LANGUAGE RankNTypes #-}
6+ {-# LANGUAGE ScopedTypeVariables #-}
67{-# LANGUAGE Trustworthy #-}
78{-# LANGUAGE TypeFamilies #-}
89{-# LANGUAGE UndecidableInstances #-}
@@ -29,11 +30,15 @@ module System.Random.Stateful
2930 -- $interfaces
3031 , StatefulGen (.. )
3132 , FrozenGen (.. )
32- , RandomGenM (.. )
3333 , withMutableGen
3434 , withMutableGen_
3535 , randomM
3636 , randomRM
37+ , splitFrozenM
38+ , splitMutableM
39+
40+ -- ** Deprecated
41+ , RandomGenM (.. )
3742 , splitGenM
3843
3944 -- * Monadic adapters for pure pseudo-random number generators #monadicadapters#
@@ -216,13 +221,16 @@ import System.Random.Internal
216221-- @since 1.2.0
217222class (RandomGen r , StatefulGen g m ) => RandomGenM g r m | g -> r where
218223 applyRandomGenM :: (r -> (a , r )) -> g -> m a
224+ {-# DEPRECATED applyRandomGenM "In favor of `modifyM`" #-}
225+ {-# DEPRECATED RandomGenM "In favor of `FrozenGen`" #-}
219226
220227-- | Splits a pseudo-random number generator into two. Overwrites the mutable
221228-- wrapper with one of the resulting generators and returns the other.
222229--
223230-- @since 1.2.0
224231splitGenM :: RandomGenM g r m => g -> m r
225232splitGenM = applyRandomGenM split
233+ {-# DEPRECATED splitGenM "In favor of `splitM`" #-}
226234
227235instance (RandomGen r , MonadIO m ) => RandomGenM (IOGenM r ) r m where
228236 applyRandomGenM = applyIOGen
@@ -301,8 +309,8 @@ uniformListM n gen = replicateM n (uniformM gen)
301309-- 0.6268211351114487
302310--
303311-- @since 1.2.0
304- randomM :: (Random a , RandomGenM g r m ) => g -> m a
305- randomM = applyRandomGenM random
312+ randomM :: forall a g m . (Random a , RandomGen g , FrozenGen g m ) => MutableGen g m -> m a
313+ randomM = flip modifyM random
306314
307315-- | Generates a pseudo-random value using monadic interface and `Random` instance.
308316--
@@ -321,8 +329,8 @@ randomM = applyRandomGenM random
321329-- 2
322330--
323331-- @since 1.2.0
324- randomRM :: (Random a , RandomGenM g r m ) => (a , a ) -> g -> m a
325- randomRM r = applyRandomGenM (randomR r)
332+ randomRM :: forall a g m . (Random a , RandomGen g , FrozenGen g m ) => (a , a ) -> MutableGen g m -> m a
333+ randomRM r = flip modifyM (randomR r)
326334
327335-- | Wraps an 'IORef' that holds a pure pseudo-random number generator. All
328336-- operations are performed atomically.
@@ -379,6 +387,11 @@ instance (RandomGen g, MonadIO m) => FrozenGen (AtomicGen g) m where
379387 type MutableGen (AtomicGen g ) m = AtomicGenM g
380388 freezeGen = fmap AtomicGen . liftIO . readIORef . unAtomicGenM
381389 thawGen (AtomicGen g) = newAtomicGenM g
390+ modifyM (AtomicGenM ioRef) f =
391+ liftIO $ atomicModifyIORef' ioRef $ \ g ->
392+ case f (AtomicGen g) of
393+ (a, AtomicGen g') -> (g', a)
394+ {-# INLINE modifyM #-}
382395
383396-- | Atomically applies a pure operation to the wrapped pseudo-random number
384397-- generator.
@@ -454,7 +467,12 @@ instance (RandomGen g, MonadIO m) => FrozenGen (IOGen g) m where
454467 type MutableGen (IOGen g ) m = IOGenM g
455468 freezeGen = fmap IOGen . liftIO . readIORef . unIOGenM
456469 thawGen (IOGen g) = newIOGenM g
457-
470+ modifyM (IOGenM ref) f = liftIO $ do
471+ g <- readIORef ref
472+ let (a, IOGen g') = f (IOGen g)
473+ g' `seq` writeIORef ref g'
474+ pure a
475+ {-# INLINE modifyM #-}
458476
459477-- | Applies a pure operation to the wrapped pseudo-random number generator.
460478--
@@ -514,6 +532,12 @@ instance RandomGen g => FrozenGen (STGen g) (ST s) where
514532 type MutableGen (STGen g ) (ST s ) = STGenM g s
515533 freezeGen = fmap STGen . readSTRef . unSTGenM
516534 thawGen (STGen g) = newSTGenM g
535+ modifyM (STGenM ref) f = do
536+ g <- readSTRef ref
537+ let (a, STGen g') = f (STGen g)
538+ g' `seq` writeSTRef ref g'
539+ pure a
540+ {-# INLINE modifyM #-}
517541
518542
519543-- | Applies a pure operation to the wrapped pseudo-random number generator.
@@ -609,6 +633,12 @@ instance RandomGen g => FrozenGen (TGen g) STM where
609633 type MutableGen (TGen g ) STM = TGenM g
610634 freezeGen = fmap TGen . readTVar . unTGenM
611635 thawGen (TGen g) = newTGenM g
636+ modifyM (TGenM ref) f = do
637+ g <- readTVar ref
638+ let (a, TGen g') = f (TGen g)
639+ g' `seq` writeTVar ref g'
640+ pure a
641+ {-# INLINE modifyM #-}
612642
613643
614644-- | Applies a pure operation to the wrapped pseudo-random number generator.
0 commit comments