Skip to content

Commit 5ce327f

Browse files
committed
Introduce uniformList, shuffleList and shuffleListM
1 parent 632b64e commit 5ce327f

4 files changed

Lines changed: 81 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
* Add default implementation for `uniformRM` using `Generics`:
55
[#92](https://github.com/haskell/random/pull/92)
66

7+
# 1.2.2
8+
9+
* Add: `uniformList`
10+
* Add: `shuffleList` and `shuffleListM`
11+
712
# 1.2.1
813

914
* Fix support for ghc-9.2 [#99](https://github.com/haskell/random/pull/99)

src/System/Random.hs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ module System.Random
2323
RandomGen(..)
2424
, uniform
2525
, uniformR
26+
, uniformList
27+
, shuffleList
2628
, genByteString
2729
, Random(..)
2830
, Uniform
@@ -188,6 +190,37 @@ uniformR :: (UniformRange a, RandomGen g) => (a, a) -> g -> (a, g)
188190
uniformR r g = runStateGen g (uniformRM r)
189191
{-# INLINE uniformR #-}
190192

193+
194+
-- | Produce a list of the supplied length with elements generated uniformly.
195+
--
196+
-- See `uniformListM` for a stateful counterpart.
197+
--
198+
-- ====__Examples__
199+
--
200+
-- >>> let gen = mkStdGen 2023
201+
-- >>> import Data.Word (Word16)
202+
-- >>> uniformList 5 gen :: ([Word16], StdGen)
203+
-- ([56342,15850,25292,14347,13919],StdGen {unStdGen = SMGen 6446154349414395371 1920468677557965761})
204+
--
205+
-- @since 1.2.2
206+
uniformList :: (Uniform a, RandomGen g) => Int -> g -> ([a], g)
207+
uniformList r g = runStateGen g (uniformListM r)
208+
{-# INLINE uniformList #-}
209+
210+
211+
-- | Shuffle elements of a list in a random order.
212+
--
213+
-- ====__Examples__
214+
--
215+
-- >>> let gen = mkStdGen 2023
216+
-- >>> shuffleList ['a'..'z'] gen
217+
-- ("renlhfqmgptwksdiyavbxojzcu",StdGen {unStdGen = SMGen 9882508430712573120 1920468677557965761})
218+
--
219+
-- @since 1.2.2
220+
shuffleList :: RandomGen g => [a] -> g -> ([a], g)
221+
shuffleList xs g = runStateGen g (shuffleListM xs)
222+
{-# INLINE shuffleList #-}
223+
191224
-- | Generates a 'ByteString' of the specified size using a pure pseudo-random
192225
-- number generator. See 'uniformByteStringM' for the monadic version.
193226
--

src/System/Random/Internal.hs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ module System.Random.Internal
5959
, uniformFloatPositive01M
6060
, uniformEnumM
6161
, uniformEnumRM
62+
, uniformListM
63+
, shuffleListM
6264

6365
-- * Generators for sequences of pseudo-random bytes
6466
, genShortByteStringIO
@@ -67,7 +69,7 @@ module System.Random.Internal
6769

6870
import Control.Arrow
6971
import Control.DeepSeq (NFData)
70-
import Control.Monad (when)
72+
import Control.Monad (when, replicateM)
7173
import Control.Monad.Cont (ContT, runContT)
7274
import Control.Monad.IO.Class (MonadIO(..))
7375
import Control.Monad.ST
@@ -78,6 +80,7 @@ import Data.Bits
7880
import Data.ByteString.Short.Internal (ShortByteString(SBS), fromShort)
7981
import Data.IORef (IORef, newIORef)
8082
import Data.Int
83+
import Data.List (sortOn)
8184
import Data.Word
8285
import Foreign.C.Types
8386
import Foreign.Storable (Storable)
@@ -541,6 +544,41 @@ runStateGenST_ g action = runST $ runStateGenT_ g action
541544
{-# INLINE runStateGenST_ #-}
542545

543546

547+
-- | Generates a list of pseudo-random values.
548+
--
549+
-- ====__Examples__
550+
--
551+
-- >>> import System.Random.Stateful
552+
-- >>> let pureGen = mkStdGen 137
553+
-- >>> g <- newIOGenM pureGen
554+
-- >>> uniformListM 10 g :: IO [Bool]
555+
-- [True,True,True,True,False,True,True,False,False,False]
556+
--
557+
-- @since 1.2.0
558+
uniformListM :: (StatefulGen g m, Uniform a) => Int -> g -> m [a]
559+
uniformListM n gen = replicateM n (uniformM gen)
560+
{-# INLINE uniformListM #-}
561+
562+
-- | Shuffle elements of a list in a random order.
563+
--
564+
-- ====__Examples__
565+
--
566+
-- >>> import System.Random.Stateful
567+
-- >>> let pureGen = mkStdGen 2023
568+
-- >>> g <- newIOGenM pureGen
569+
-- >>> shuffleListM ['a'..'z'] g :: IO String
570+
-- "renlhfqmgptwksdiyavbxojzcu"
571+
--
572+
-- @since 1.2.2
573+
shuffleListM :: StatefulGen g m => [a] -> g -> m [a]
574+
shuffleListM xs gen = do
575+
is <- uniformListM n gen
576+
pure $ map snd $ sortOn fst $ zip (is :: [Int]) xs
577+
where
578+
!n = length xs
579+
{-# INLINE shuffleListM #-}
580+
581+
544582
-- | The standard pseudo-random number generator.
545583
newtype StdGen = StdGen { unStdGen :: SM.SMGen }
546584
deriving (Show, RandomGen, NFData)

src/System/Random/Stateful.hs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,13 @@ module System.Random.Stateful
7676
-- * Pseudo-random values of various types
7777
-- $uniform
7878
, Uniform(..)
79-
, uniformListM
8079
, uniformViaFiniteM
8180
, UniformRange(..)
8281

82+
-- * Lists
83+
, uniformListM
84+
, shuffleListM
85+
8386
-- * Generators for sequences of pseudo-random bytes
8487
, genShortByteStringIO
8588
, genShortByteStringST
@@ -104,7 +107,6 @@ module System.Random.Stateful
104107
) where
105108

106109
import Control.DeepSeq
107-
import Control.Monad (replicateM)
108110
import Control.Monad.IO.Class
109111
import Control.Monad.ST
110112
import GHC.Conc.Sync (STM, TVar, newTVar, newTVarIO, readTVar, writeTVar)
@@ -274,20 +276,6 @@ withMutableGen_ :: FrozenGen f m => f -> (MutableGen f m -> m a) -> m a
274276
withMutableGen_ fg action = fst <$> withMutableGen fg action
275277

276278

277-
-- | Generates a list of pseudo-random values.
278-
--
279-
-- ====__Examples__
280-
--
281-
-- >>> import System.Random.Stateful
282-
-- >>> let pureGen = mkStdGen 137
283-
-- >>> g <- newIOGenM pureGen
284-
-- >>> uniformListM 10 g :: IO [Bool]
285-
-- [True,True,True,True,False,True,True,False,False,False]
286-
--
287-
-- @since 1.2.0
288-
uniformListM :: (StatefulGen g m, Uniform a) => Int -> g -> m [a]
289-
uniformListM n gen = replicateM n (uniformM gen)
290-
291279
-- | Generates a pseudo-random value using monadic interface and `Random` instance.
292280
--
293281
-- ====__Examples__

0 commit comments

Comments
 (0)