• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

haskell / random / 432

05 Jul 2025 07:13PM UTC coverage: 69.035% (+0.3%) from 68.696%
432

push

github

web-flow
Merge a02eb707e into 1592c8382

141 of 209 new or added lines in 6 files covered. (67.46%)

98 existing lines in 6 files now uncovered.

651 of 943 relevant lines covered (69.03%)

1.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.75
/src/System/Random.hs
1
{-# LANGUAGE BangPatterns #-}
2
{-# LANGUAGE CPP #-}
3
{-# LANGUAGE DefaultSignatures #-}
4
{-# LANGUAGE MagicHash #-}
5
{-# LANGUAGE Trustworthy #-}
6

7
-- |
8
-- Module      :  System.Random
9
-- Copyright   :  (c) The University of Glasgow 2001
10
-- License     :  BSD-style (see the file LICENSE in the 'random' repository)
11
-- Maintainer  :  libraries@haskell.org
12
-- Stability   :  stable
13
--
14
-- This library deals with the common task of pseudo-random number generation.
15
module System.Random (
16
  -- * Introduction
17
  -- $introduction
18

19
  -- * Usage
20
  -- $usagepure
21

22
  -- * Pure number generator interface
23
  -- $interfaces
24
  RandomGen (
25
    split,
26
    genWord8,
27
    genWord16,
28
    genWord32,
29
    genWord64,
30
    genWord32R,
31
    genWord64R,
32
    unsafeUniformFillMutableByteArray
33
  ),
34
  SplitGen (splitGen),
35
  uniform,
36
  uniformR,
37
  Random (..),
38
  Uniform,
39
  UniformRange,
40
  Finite,
41

42
  -- ** Seed
43
  module System.Random.Seed,
44

45
  -- * Generators for sequences of pseudo-random bytes
46

47
  -- ** Lists
48
  uniforms,
49
  uniformRs,
50
  uniformList,
51
  uniformListR,
52
  uniformShuffleList,
53

54
  -- ** Bytes
55
  uniformByteArray,
56
  uniformByteString,
57
  uniformShortByteString,
58
  uniformFillMutableByteArray,
59

60
  -- *** Deprecated
61
  genByteString,
62
  genShortByteString,
63

64
  -- ** Standard pseudo-random number generator
65
  StdGen,
66
  mkStdGen,
67
  mkStdGen64,
68
  initStdGen,
69

70
  -- ** Global standard pseudo-random number generator
71
  -- $globalstdgen
72
  getStdRandom,
73
  getStdGen,
74
  setStdGen,
75
  newStdGen,
76
  randomIO,
77
  randomRIO,
78

79
  -- * Compatibility and reproducibility
80

81
  -- ** Backwards compatibility and deprecations
82
  genRange,
83
  next,
84
  -- $deprecations
85

86
  -- ** Reproducibility
87
  -- $reproducibility
88

89
  -- * Notes for pseudo-random number generator implementors
90

91
  -- ** How to implement 'RandomGen'
92
  -- $implementrandomgen
93

94
  -- * References
95
  -- $references
96
) where
97

98
import Control.Arrow
99
import Control.Monad.IO.Class
100
import Control.Monad.ST (ST)
101
import Control.Monad.State.Strict
102
import Data.Array.Byte (ByteArray (..), MutableByteArray (..))
103
import Data.ByteString (ByteString)
104
import Data.ByteString.Short.Internal (ShortByteString (..))
105
import Data.IORef
106
import Data.Int
107
import Data.Word
108
import Foreign.C.Types
109
import GHC.Exts
110
import System.Random.Array (getSizeOfMutableByteArray, shortByteStringToByteString, shuffleListST)
111
import System.Random.GFinite (Finite)
112
import System.Random.Internal hiding (uniformShortByteString)
113
import System.Random.Seed
114
import qualified System.Random.SplitMix as SM
115

116
-- $introduction
117
--
118
-- This module provides type classes and instances for the following concepts:
119
--
120
-- [Pure pseudo-random number generators] 'RandomGen' is an interface to pure
121
--     pseudo-random number generators.
122
--
123
--     'StdGen', the standard pseudo-random number generator provided in this
124
--     library, is an instance of 'RandomGen'. It uses the SplitMix
125
--     implementation provided by the
126
--     <https://hackage.haskell.org/package/splitmix splitmix> package.
127
--     Programmers may, of course, supply their own instances of 'RandomGen'.
128

129
-- $usagepure
130
--
131
-- In pure code, use 'uniform' and 'uniformR' to generate pseudo-random values
132
-- with a pure pseudo-random number generator like 'StdGen'.
133
--
134
-- >>> :{
135
-- let rolls :: RandomGen g => Int -> g -> [Word]
136
--     rolls n = fst . uniformListR n (1, 6)
137
--     pureGen = mkStdGen 137
138
-- in
139
--     rolls 10 pureGen :: [Word]
140
-- :}
141
-- [4,2,6,1,6,6,5,1,1,5]
142
--
143
-- To run use a /monadic/ pseudo-random computation in pure code with a pure
144
-- pseudo-random number generator, use 'runStateGen' and its variants.
145
--
146
-- >>> :{
147
-- let rollsM :: StatefulGen g m => Int -> g -> m [Word]
148
--     rollsM n = uniformListRM n (1, 6)
149
--     pureGen = mkStdGen 137
150
-- in
151
--     runStateGen_ pureGen (rollsM 10) :: [Word]
152
-- :}
153
-- [4,2,6,1,6,6,5,1,1,5]
154

155
-------------------------------------------------------------------------------
156
-- Pseudo-random number generator interfaces
157
-------------------------------------------------------------------------------
158

159
-- $interfaces
160
--
161
-- Pseudo-random number generators come in two flavours: /pure/ and /monadic/.
162
--
163
-- ['RandomGen': pure pseudo-random number generators] These generators produce
164
--     a new pseudo-random value together with a new instance of the
165
--     pseudo-random number generator.
166
--
167
--     Pure pseudo-random number generators should implement 'split' if they
168
--     are /splittable/, that is, if there is an efficient method to turn one
169
--     generator into two. The pseudo-random numbers produced by the two
170
--     resulting generators should not be correlated. See [1] for some
171
--     background on splittable pseudo-random generators.
172
--
173
-- ['System.Random.Stateful.StatefulGen': monadic pseudo-random number generators]
174
--     See "System.Random.Stateful" module
175

176
-- | Generates a value uniformly distributed over all possible values of that
177
-- type.
178
--
179
-- This is a pure version of 'System.Random.Stateful.uniformM'.
180
--
181
-- ====__Examples__
182
--
183
-- >>> import System.Random
184
-- >>> let pureGen = mkStdGen 137
185
-- >>> uniform pureGen :: (Bool, StdGen)
186
-- (True,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
187
--
188
-- You can use type applications to disambiguate the type of the generated numbers:
189
--
190
-- >>> :seti -XTypeApplications
191
-- >>> uniform @Bool pureGen
192
-- (True,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
193
--
194
-- @since 1.2.0
195
uniform :: (Uniform a, RandomGen g) => g -> (a, g)
196
uniform g = runStateGen g uniformM
2✔
197
{-# INLINE uniform #-}
198

199
-- | Generates a value uniformly distributed over the provided range, which
200
-- is interpreted as inclusive in the lower and upper bound.
201
--
202
-- *   @uniformR (1 :: Int, 4 :: Int)@ generates values uniformly from the set
203
--     \(\{1,2,3,4\}\)
204
--
205
-- *   @uniformR (1 :: Float, 4 :: Float)@ generates values uniformly from the
206
--     set \(\{x\;|\;1 \le x \le 4\}\)
207
--
208
-- The following law should hold to make the function always defined:
209
--
210
-- > uniformR (a, b) = uniformR (b, a)
211
--
212
-- This is a pure version of 'System.Random.Stateful.uniformRM'.
213
--
214
-- ====__Examples__
215
--
216
-- >>> import System.Random
217
-- >>> let pureGen = mkStdGen 137
218
-- >>> uniformR (1 :: Int, 4 :: Int) pureGen
219
-- (4,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
220
--
221
-- You can use type applications to disambiguate the type of the generated numbers:
222
--
223
-- >>> :seti -XTypeApplications
224
-- >>> uniformR @Int (1, 4) pureGen
225
-- (4,StdGen {unStdGen = SMGen 11285859549637045894 7641485672361121627})
226
--
227
-- @since 1.2.0
228
uniformR :: (UniformRange a, RandomGen g) => (a, a) -> g -> (a, g)
229
uniformR r g = runStateGen g (uniformRM r)
2✔
230
{-# INLINE uniformR #-}
231

232
-- | Produce an infinite list of pseudo-random values. Integrates nicely with list
233
-- fusion. Naturally, there is no way to recover the final generator, therefore either use
234
-- `split` before calling `uniforms` or use `uniformList` instead.
235
--
236
-- Similar to `randoms`, except it relies on `Uniform` type class instead of `Random`
237
--
238
-- ====__Examples__
239
--
240
-- >>> let gen = mkStdGen 2023
241
-- >>> import Data.Word (Word16)
242
-- >>> take 5 $ uniforms gen :: [Word16]
243
-- [56342,15850,25292,14347,13919]
244
--
245
-- @since 1.3.0
246
uniforms :: (Uniform a, RandomGen g) => g -> [a]
247
uniforms g0 =
2✔
248
  build $ \cons _nil ->
2✔
249
    let go g =
2✔
250
          case uniform g of
2✔
251
            (x, g') -> x `seq` (x `cons` go g')
2✔
252
     in go g0
2✔
253
{-# INLINE uniforms #-}
254

255
-- | Produce an infinite list of pseudo-random values in a specified range. Same as
256
-- `uniforms`, integrates nicely with list fusion. There is no way to recover the final
257
-- generator, therefore either use `split` before calling `uniformRs` or use
258
-- `uniformListR` instead.
259
--
260
-- Similar to `randomRs`, except it relies on `UniformRange` type class instead of
261
-- `Random`.
262
--
263
-- ====__Examples__
264
--
265
-- >>> let gen = mkStdGen 2023
266
-- >>> take 5 $ uniformRs (10, 100) gen :: [Int]
267
-- [32,86,21,57,39]
268
--
269
-- @since 1.3.0
270
uniformRs :: (UniformRange a, RandomGen g) => (a, a) -> g -> [a]
271
uniformRs range g0 =
2✔
272
  build $ \cons _nil ->
2✔
273
    let go g =
2✔
274
          case uniformR range g of
2✔
275
            (x, g') -> x `seq` (x `cons` go g')
2✔
276
     in go g0
2✔
277
{-# INLINE uniformRs #-}
278

279
-- | Produce a list of the supplied length with elements generated uniformly.
280
--
281
-- See `uniformListM` for a stateful counterpart.
282
--
283
-- ====__Examples__
284
--
285
-- >>> let gen = mkStdGen 2023
286
-- >>> import Data.Word (Word16)
287
-- >>> uniformList 5 gen :: ([Word16], StdGen)
288
-- ([56342,15850,25292,14347,13919],StdGen {unStdGen = SMGen 6446154349414395371 1920468677557965761})
289
--
290
-- @since 1.3.0
291
uniformList :: (Uniform a, RandomGen g) => Int -> g -> ([a], g)
292
uniformList n g = runStateGen g (uniformListM n)
2✔
293
{-# INLINE uniformList #-}
294

295
-- | Produce a list of the supplied length with elements generated uniformly.
296
--
297
-- See `uniformListM` for a stateful counterpart.
298
--
299
-- ====__Examples__
300
--
301
-- >>> let gen = mkStdGen 2023
302
-- >>> uniformListR 10 (20, 30) gen :: ([Int], StdGen)
303
-- ([26,30,27,24,30,25,27,21,27,27],StdGen {unStdGen = SMGen 12965503083958398648 1920468677557965761})
304
--
305
-- @since 1.3.0
306
uniformListR :: (UniformRange a, RandomGen g) => Int -> (a, a) -> g -> ([a], g)
307
uniformListR n r g = runStateGen g (uniformListRM n r)
2✔
308
{-# INLINE uniformListR #-}
309

310
-- | Shuffle elements of a list in a uniformly random order.
311
--
312
-- ====__Examples__
313
--
314
-- >>> uniformShuffleList "ELVIS" $ mkStdGen 252
315
-- ("LIVES",StdGen {unStdGen = SMGen 17676540583805057877 5302934877338729551})
316
--
317
-- @since 1.3.0
318
uniformShuffleList :: RandomGen g => [a] -> g -> ([a], g)
319
uniformShuffleList xs g =
2✔
320
  runStateGenST g $ \gen -> shuffleListST (`uniformWordR` gen) xs
1✔
321
{-# INLINE uniformShuffleList #-}
322

323
-- | Generates a 'ByteString' of the specified size using a pure pseudo-random
324
-- number generator. See 'uniformByteStringM' for the monadic version.
325
--
326
-- ====__Examples__
327
--
328
-- >>> import System.Random
329
-- >>> import Data.ByteString
330
-- >>> let pureGen = mkStdGen 137
331
-- >>> :seti -Wno-deprecations
332
-- >>> unpack . fst . genByteString 10 $ pureGen
333
-- [51,123,251,37,49,167,90,109,1,4]
334
--
335
-- @since 1.2.0
336
genByteString :: RandomGen g => Int -> g -> (ByteString, g)
UNCOV
337
genByteString = uniformByteString
×
338
{-# INLINE genByteString #-}
339
{-# DEPRECATED genByteString "In favor of `uniformByteString`" #-}
340

341
-- | Generates a 'ByteString' of the specified size using a pure pseudo-random
342
-- number generator. See 'uniformByteStringM' for the monadic version.
343
--
344
-- ====__Examples__
345
--
346
-- >>> import System.Random
347
-- >>> import Data.ByteString (unpack)
348
-- >>> let pureGen = mkStdGen 137
349
-- >>> unpack . fst $ uniformByteString 10 pureGen
350
-- [51,123,251,37,49,167,90,109,1,4]
351
--
352
-- @since 1.3.0
353
uniformByteString :: RandomGen g => Int -> g -> (ByteString, g)
354
uniformByteString n g =
2✔
355
  case uniformByteArray True n g of
2✔
356
    (byteArray, g') ->
357
      (shortByteStringToByteString $ byteArrayToShortByteString byteArray, g')
2✔
358
{-# INLINE uniformByteString #-}
359

360
-- | Same as @`uniformByteArray` `False`@, but for `ShortByteString`.
361
--
362
-- Returns a 'ShortByteString' of length @n@ filled with pseudo-random bytes.
363
--
364
-- ====__Examples__
365
--
366
-- >>> import System.Random
367
-- >>> import Data.ByteString.Short (unpack)
368
-- >>> let pureGen = mkStdGen 137
369
-- >>> unpack . fst $ uniformShortByteString 10 pureGen
370
-- [51,123,251,37,49,167,90,109,1,4]
371
--
372
-- @since 1.3.0
373
uniformShortByteString :: RandomGen g => Int -> g -> (ShortByteString, g)
374
uniformShortByteString n g =
2✔
375
  case uniformByteArray False n g of
2✔
376
    (ByteArray ba#, g') -> (SBS ba#, g')
2✔
377
{-# INLINE uniformShortByteString #-}
378

379
-- | Fill in a slice of a mutable byte array with randomly generated bytes. This function
380
-- does not fail, instead it clamps the offset and number of bytes to generate into a valid
381
-- range.
382
--
383
-- @since 1.3.0
384
uniformFillMutableByteArray ::
385
  RandomGen g =>
386
  -- | Mutable array to fill with random bytes
387
  MutableByteArray s ->
388
  -- | Offset into a mutable array from the beginning in number of bytes. Offset will be
389
  -- clamped into the range between 0 and the total size of the mutable array
390
  Int ->
391
  -- | Number of randomly generated bytes to write into the array. This number will be
392
  -- clamped between 0 and the total size of the array without the offset.
393
  Int ->
394
  g ->
395
  ST s g
396
uniformFillMutableByteArray mba i0 n g = do
2✔
397
  !sz <- getSizeOfMutableByteArray mba
2✔
398
  let !offset = max 0 (min sz i0)
2✔
399
      !numBytes = min (sz - offset) (max 0 n)
2✔
400
  unsafeUniformFillMutableByteArray mba offset numBytes g
2✔
401
{-# INLINE uniformFillMutableByteArray #-}
402

403
-- | The class of types for which random values can be generated. Most
404
-- instances of `Random` will produce values that are uniformly distributed on the full
405
-- range, but for those types without a well-defined "full range" some sensible default
406
-- subrange will be selected.
407
--
408
-- 'Random' exists primarily for backwards compatibility with version 1.1 of
409
-- this library. In new code, use the better specified 'Uniform' and
410
-- 'UniformRange' instead.
411
--
412
-- @since 1.0.0
413
class Random a where
414
  -- | Takes a range /(lo,hi)/ and a pseudo-random number generator
415
  -- /g/, and returns a pseudo-random value uniformly distributed over the
416
  -- closed interval /[lo,hi]/, together with a new generator. It is unspecified
417
  -- what happens if /lo>hi/, but usually the values will simply get swapped.
418
  --
419
  -- >>> let gen = mkStdGen 26
420
  -- >>> fst $ randomR ('a', 'z') gen
421
  -- 'z'
422
  -- >>> fst $ randomR ('a', 'z') gen
423
  -- 'z'
424
  --
425
  -- For continuous types there is no requirement that the values /lo/ and /hi/ are ever
426
  -- produced, but they may be, depending on the implementation and the interval.
427
  --
428
  -- There is no requirement to follow the @Ord@ instance and the concept of range can be
429
  -- defined on per type basis. For example product types will treat their values
430
  -- independently:
431
  --
432
  -- >>> fst $ randomR (('a', 5.0), ('z', 10.0)) $ mkStdGen 26
433
  -- ('z',5.22694980853051)
434
  --
435
  -- In case when a lawful range is desired `uniformR` should be used
436
  -- instead.
437
  --
438
  -- @since 1.0.0
439
  {-# INLINE randomR #-}
440
  randomR :: RandomGen g => (a, a) -> g -> (a, g)
441
  default randomR :: (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
442
  randomR r g = runStateGen g (uniformRM r)
2✔
443

444
  -- | The same as 'randomR', but using a default range determined by the type:
445
  --
446
  -- * For bounded types (instances of 'Bounded', such as 'Char'),
447
  --   the range is normally the whole type.
448
  --
449
  -- * For floating point types, the range is normally the closed interval @[0,1]@.
450
  --
451
  -- * For 'Integer', the range is (arbitrarily) the range of 'Int'.
452
  --
453
  -- @since 1.0.0
454
  {-# INLINE random #-}
455
  random :: RandomGen g => g -> (a, g)
456
  default random :: (RandomGen g, Uniform a) => g -> (a, g)
457
  random g = runStateGen g uniformM
2✔
458

459
  -- | Plural variant of 'randomR', producing an infinite list of
460
  -- pseudo-random values instead of returning a new generator.
461
  --
462
  -- @since 1.0.0
463
  {-# INLINE randomRs #-}
464
  randomRs :: RandomGen g => (a, a) -> g -> [a]
465
  randomRs ival g = build (\cons _nil -> buildRandoms cons (randomR ival) g)
2✔
466

467
  -- | Plural variant of 'random', producing an infinite list of
468
  -- pseudo-random values instead of returning a new generator.
469
  --
470
  -- @since 1.0.0
471
  {-# INLINE randoms #-}
472
  randoms :: RandomGen g => g -> [a]
473
  randoms g = build (\cons _nil -> buildRandoms cons random g)
2✔
474

475
-- | Produce an infinite list-equivalent of pseudo-random values.
476
--
477
-- ====__Examples__
478
--
479
-- >>> import System.Random
480
-- >>> let pureGen = mkStdGen 137
481
-- >>> (take 4 . buildRandoms (:) random $ pureGen) :: [Int]
482
-- [7879794327570578227,6883935014316540929,-1519291874655152001,2353271688382626589]
483
{-# INLINE buildRandoms #-}
484
buildRandoms ::
485
  -- | E.g. @(:)@ but subject to fusion
486
  (a -> as -> as) ->
487
  -- | E.g. 'random'
488
  (g -> (a, g)) ->
489
  -- | A 'RandomGen' instance
490
  g ->
491
  as
492
buildRandoms cons rand = go
2✔
493
  where
494
    -- The seq fixes part of #4218 and also makes fused Core simpler:
495
    -- https://gitlab.haskell.org/ghc/ghc/-/issues/4218
496
    go g = x `seq` (x `cons` go g') where (x, g') = rand g
2✔
497

498
-- | /Note/ - `random` generates values in the `Int` range
499
instance Random Integer where
500
  random = first (toInteger :: Int -> Integer) . random
2✔
501
  {-# INLINE random #-}
502

503
instance Random Int8
504

505
instance Random Int16
506

507
instance Random Int32
508

509
instance Random Int64
510

511
instance Random Int
512

513
instance Random Word
514

515
instance Random Word8
516

517
instance Random Word16
518

519
instance Random Word32
520

521
instance Random Word64
522
#if __GLASGOW_HASKELL__ >= 802
523
instance Random CBool
524
#endif
525
instance Random CChar
526

527
instance Random CSChar
528

529
instance Random CUChar
530

531
instance Random CShort
532

533
instance Random CUShort
534

535
instance Random CInt
536

537
instance Random CUInt
538

539
instance Random CLong
540

541
instance Random CULong
542

543
instance Random CPtrdiff
544

545
instance Random CSize
546

547
instance Random CWchar
548

549
instance Random CSigAtomic
550

551
instance Random CLLong
552

553
instance Random CULLong
554

555
instance Random CIntPtr
556

557
instance Random CUIntPtr
558

559
instance Random CIntMax
560

561
instance Random CUIntMax
562

563
-- | /Note/ - `random` produces values in the closed range @[0,1]@.
564
instance Random CFloat where
565
  randomR r = coerce . randomR (coerce r :: (Float, Float))
2✔
566
  {-# INLINE randomR #-}
567
  random = first CFloat . random
2✔
568
  {-# INLINE random #-}
569

570
-- | /Note/ - `random` produces values in the closed range @[0,1]@.
571
instance Random CDouble where
572
  randomR r = coerce . randomR (coerce r :: (Double, Double))
2✔
573
  {-# INLINE randomR #-}
574
  random = first CDouble . random
2✔
575
  {-# INLINE random #-}
576

577
instance Random Char
578

579
instance Random Bool
580

581
-- | /Note/ - `random` produces values in the closed range @[0,1]@.
582
instance Random Double where
583
  randomR r g = runStateGen g (uniformRM r)
2✔
584
  {-# INLINE randomR #-}
585

586
  -- We return 1 - uniformDouble01M here for backwards compatibility with
587
  -- v1.2.0. Just return the result of uniformDouble01M in the next major
588
  -- version.
589
  random g = runStateGen g (fmap (1 -) . uniformDouble01M)
2✔
590
  {-# INLINE random #-}
591

592
-- | /Note/ - `random` produces values in the closed range @[0,1]@.
593
instance Random Float where
594
  randomR r g = runStateGen g (uniformRM r)
2✔
595
  {-# INLINE randomR #-}
596

597
  -- We return 1 - uniformFloat01M here for backwards compatibility with
598
  -- v1.2.0. Just return the result of uniformFloat01M in the next major
599
  -- version.
600
  random g = runStateGen g (fmap (1 -) . uniformFloat01M)
2✔
601
  {-# INLINE random #-}
602

603
-- | Initialize 'StdGen' using system entropy (i.e. @\/dev\/urandom@) when it is
604
-- available, while falling back on using system time as the seed.
605
--
606
-- @since 1.2.1
607
initStdGen :: MonadIO m => m StdGen
UNCOV
608
initStdGen = liftIO (StdGen <$> SM.initSMGen)
×
609

610
-- | /Note/ - `randomR` treats @a@ and @b@ types independently
611
instance (Random a, Random b) => Random (a, b) where
612
  randomR ((al, bl), (ah, bh)) =
2✔
613
    runState $
2✔
614
      (,) <$> state (randomR (al, ah)) <*> state (randomR (bl, bh))
2✔
615
  {-# INLINE randomR #-}
616
  random = runState $ (,) <$> state random <*> state random
2✔
617
  {-# INLINE random #-}
618

619
-- | /Note/ - `randomR` treats @a@, @b@ and @c@ types independently
620
instance (Random a, Random b, Random c) => Random (a, b, c) where
621
  randomR ((al, bl, cl), (ah, bh, ch)) =
2✔
622
    runState $
2✔
623
      (,,)
2✔
624
        <$> state (randomR (al, ah))
2✔
625
        <*> state (randomR (bl, bh))
2✔
626
        <*> state (randomR (cl, ch))
2✔
627
  {-# INLINE randomR #-}
628
  random = runState $ (,,) <$> state random <*> state random <*> state random
2✔
629
  {-# INLINE random #-}
630

631
-- | /Note/ - `randomR` treats @a@, @b@, @c@ and @d@ types independently
632
instance (Random a, Random b, Random c, Random d) => Random (a, b, c, d) where
633
  randomR ((al, bl, cl, dl), (ah, bh, ch, dh)) =
2✔
634
    runState $
2✔
635
      (,,,)
2✔
636
        <$> state (randomR (al, ah))
2✔
637
        <*> state (randomR (bl, bh))
2✔
638
        <*> state (randomR (cl, ch))
2✔
639
        <*> state (randomR (dl, dh))
2✔
640
  {-# INLINE randomR #-}
641
  random =
2✔
642
    runState $
2✔
643
      (,,,) <$> state random <*> state random <*> state random <*> state random
2✔
644
  {-# INLINE random #-}
645

646
-- | /Note/ - `randomR` treats @a@, @b@, @c@, @d@ and @e@ types independently
647
instance (Random a, Random b, Random c, Random d, Random e) => Random (a, b, c, d, e) where
648
  randomR ((al, bl, cl, dl, el), (ah, bh, ch, dh, eh)) =
2✔
649
    runState $
2✔
650
      (,,,,)
2✔
651
        <$> state (randomR (al, ah))
2✔
652
        <*> state (randomR (bl, bh))
2✔
653
        <*> state (randomR (cl, ch))
2✔
654
        <*> state (randomR (dl, dh))
2✔
655
        <*> state (randomR (el, eh))
2✔
656
  {-# INLINE randomR #-}
657
  random =
2✔
658
    runState $
2✔
659
      (,,,,) <$> state random <*> state random <*> state random <*> state random <*> state random
2✔
660
  {-# INLINE random #-}
661

662
-- | /Note/ - `randomR` treats @a@, @b@, @c@, @d@, @e@ and @f@ types independently
663
instance
664
  (Random a, Random b, Random c, Random d, Random e, Random f) =>
665
  Random (a, b, c, d, e, f)
666
  where
667
  randomR ((al, bl, cl, dl, el, fl), (ah, bh, ch, dh, eh, fh)) =
2✔
668
    runState $
2✔
669
      (,,,,,)
2✔
670
        <$> state (randomR (al, ah))
2✔
671
        <*> state (randomR (bl, bh))
2✔
672
        <*> state (randomR (cl, ch))
2✔
673
        <*> state (randomR (dl, dh))
2✔
674
        <*> state (randomR (el, eh))
2✔
675
        <*> state (randomR (fl, fh))
2✔
676
  {-# INLINE randomR #-}
677
  random =
2✔
678
    runState $
2✔
679
      (,,,,,)
2✔
680
        <$> state random
2✔
681
        <*> state random
2✔
682
        <*> state random
2✔
683
        <*> state random
2✔
684
        <*> state random
2✔
685
        <*> state random
2✔
686
  {-# INLINE random #-}
687

688
-- | /Note/ - `randomR` treats @a@, @b@, @c@, @d@, @e@, @f@ and @g@ types independently
689
instance
690
  (Random a, Random b, Random c, Random d, Random e, Random f, Random g) =>
691
  Random (a, b, c, d, e, f, g)
692
  where
693
  randomR ((al, bl, cl, dl, el, fl, gl), (ah, bh, ch, dh, eh, fh, gh)) =
2✔
694
    runState $
2✔
695
      (,,,,,,)
2✔
696
        <$> state (randomR (al, ah))
2✔
697
        <*> state (randomR (bl, bh))
2✔
698
        <*> state (randomR (cl, ch))
2✔
699
        <*> state (randomR (dl, dh))
2✔
700
        <*> state (randomR (el, eh))
2✔
701
        <*> state (randomR (fl, fh))
2✔
702
        <*> state (randomR (gl, gh))
2✔
703
  {-# INLINE randomR #-}
704
  random =
2✔
705
    runState $
2✔
706
      (,,,,,,)
2✔
707
        <$> state random
2✔
708
        <*> state random
2✔
709
        <*> state random
2✔
710
        <*> state random
2✔
711
        <*> state random
2✔
712
        <*> state random
2✔
713
        <*> state random
2✔
714
  {-# INLINE random #-}
715

716
-------------------------------------------------------------------------------
717
-- Global pseudo-random number generator
718
-------------------------------------------------------------------------------
719

720
-- $globalstdgen
721
--
722
-- There is a single, implicit, global pseudo-random number generator of type
723
-- 'StdGen', held in a global mutable variable that can be manipulated from
724
-- within the 'IO' monad. It is also available as
725
-- 'System.Random.Stateful.globalStdGen', therefore it is recommended to use the
726
-- new "System.Random.Stateful" interface to explicitly operate on the global
727
-- pseudo-random number generator.
728
--
729
-- It is initialised with 'initStdGen', although it is possible to override its
730
-- value with 'setStdGen'. All operations on the global pseudo-random number
731
-- generator are thread safe, however in presence of concurrency they are
732
-- naturally become non-deterministic. Moreover, relying on the global mutable
733
-- state makes it hard to know which of the dependent libraries are using it as
734
-- well, making it unpredictable in the local context. Precisely of this reason,
735
-- the global pseudo-random number generator is only suitable for uses in
736
-- applications, test suites, etc. and is advised against in development of
737
-- reusable libraries.
738
--
739
-- It is also important to note that either using 'StdGen' with pure functions
740
-- from other sections of this module or by relying on
741
-- 'System.Random.Stateful.runStateGen' from stateful interface does not only
742
-- give us deterministic behaviour without requiring 'IO', but it is also more
743
-- efficient.
744

745
-- | Sets the global pseudo-random number generator. Overwrites the contents of
746
-- 'System.Random.Stateful.globalStdGen'
747
--
748
-- @since 1.0.0
749
setStdGen :: MonadIO m => StdGen -> m ()
UNCOV
750
setStdGen = liftIO . writeIORef theStdGen
×
751

752
-- | Gets the global pseudo-random number generator. Extracts the contents of
753
-- 'System.Random.Stateful.globalStdGen'
754
--
755
-- @since 1.0.0
756
getStdGen :: MonadIO m => m StdGen
757
getStdGen = liftIO $ readIORef theStdGen
2✔
758

759
-- | Applies 'split' to the current global pseudo-random generator
760
-- 'System.Random.Stateful.globalStdGen', updates it with one of the results,
761
-- and returns the other.
762
--
763
-- @since 1.0.0
764
newStdGen :: MonadIO m => m StdGen
765
newStdGen = liftIO $ atomicModifyIORef' theStdGen splitGen
2✔
766

767
-- | Uses the supplied function to get a value from the current global
768
-- random generator, and updates the global generator with the new generator
769
-- returned by the function. For example, @rollDice@ produces a pseudo-random integer
770
-- between 1 and 6:
771
--
772
-- >>> rollDice = getStdRandom (randomR (1, 6))
773
-- >>> replicateM 10 (rollDice :: IO Int)
774
-- [1,1,1,4,5,6,1,2,2,5]
775
--
776
-- This is an outdated function and it is recommended to switch to its
777
-- equivalent 'System.Random.Stateful.applyAtomicGen' instead, possibly with the
778
-- 'System.Random.Stateful.globalStdGen' if relying on the global state is
779
-- acceptable.
780
--
781
-- >>> import System.Random.Stateful
782
-- >>> rollDice = applyAtomicGen (uniformR (1, 6)) globalStdGen
783
-- >>> replicateM 10 (rollDice :: IO Int)
784
-- [2,1,1,5,4,3,6,6,3,2]
785
--
786
-- @since 1.0.0
787
getStdRandom :: MonadIO m => (StdGen -> (a, StdGen)) -> m a
788
getStdRandom f = liftIO $ atomicModifyIORef' theStdGen (swap . f)
2✔
789
  where
790
    swap (v, g) = (g, v)
2✔
791

792
-- | A variant of 'System.Random.Stateful.randomRM' that uses the global
793
-- pseudo-random number generator 'System.Random.Stateful.globalStdGen'
794
--
795
-- >>> randomRIO (2020, 2100) :: IO Int
796
-- 2028
797
--
798
-- Similar to 'randomIO', this function is equivalent to @'getStdRandom'
799
-- 'randomR'@ and is included in this interface for historical reasons and
800
-- backwards compatibility. It is recommended to use
801
-- 'System.Random.Stateful.uniformRM' instead, possibly with the
802
-- 'System.Random.Stateful.globalStdGen' if relying on the global state is
803
-- acceptable.
804
--
805
-- >>> import System.Random.Stateful
806
-- >>> uniformRM (2020, 2100) globalStdGen :: IO Int
807
-- 2044
808
--
809
-- @since 1.0.0
810
randomRIO :: (Random a, MonadIO m) => (a, a) -> m a
UNCOV
811
randomRIO range = getStdRandom (randomR range)
×
812

813
-- | A variant of 'System.Random.Stateful.randomM' that uses the global
814
-- pseudo-random number generator 'System.Random.Stateful.globalStdGen'.
815
--
816
-- >>> import Data.Int
817
-- >>> randomIO :: IO Int32
818
-- 114794456
819
--
820
-- This function is equivalent to @'getStdRandom' 'random'@ and is included in
821
-- this interface for historical reasons and backwards compatibility. It is
822
-- recommended to use 'System.Random.Stateful.uniformM' instead, possibly with
823
-- the 'System.Random.Stateful.globalStdGen' if relying on the global state is
824
-- acceptable.
825
--
826
-- >>> import System.Random.Stateful
827
-- >>> uniformM globalStdGen :: IO Int32
828
-- -1768545016
829
--
830
-- @since 1.0.0
831
randomIO :: (Random a, MonadIO m) => m a
832
randomIO = getStdRandom random
2✔
833

834
-------------------------------------------------------------------------------
835
-- Notes
836
-------------------------------------------------------------------------------
837

838
-- $implementrandomgen
839
--
840
-- Consider these points when writing a 'RandomGen' instance for a given pure
841
-- pseudo-random number generator:
842
--
843
-- *   If the pseudo-random number generator has a power-of-2 modulus, that is,
844
--     it natively outputs @2^n@ bits of randomness for some @n@, implement
845
--     'genWord8', 'genWord16', 'genWord32' and 'genWord64'. See below for more
846
--     details.
847
--
848
-- *   If the pseudo-random number generator does not have a power-of-2
849
--     modulus, implement 'next' and 'genRange'. See below for more details.
850
--
851
-- *   If the pseudo-random number generator is splittable, implement 'split'.
852
--     If there is no suitable implementation, 'split' should fail with a
853
--     helpful error message.
854
--
855
-- === How to implement 'RandomGen' for a pseudo-random number generator with power-of-2 modulus
856
--
857
-- Suppose you want to implement a [permuted congruential
858
-- generator](https://en.wikipedia.org/wiki/Permuted_congruential_generator).
859
--
860
-- >>> data PCGen = PCGen !Word64 !Word64
861
--
862
-- It produces a full 'Word32' of randomness per iteration.
863
--
864
-- >>> import Data.Bits
865
-- >>> :{
866
-- let stepGen :: PCGen -> (Word32, PCGen)
867
--     stepGen (PCGen state inc) = let
868
--       newState = state * 6364136223846793005 + (inc .|. 1)
869
--       xorShifted = fromIntegral (((state `shiftR` 18) `xor` state) `shiftR` 27) :: Word32
870
--       rot = fromIntegral (state `shiftR` 59) :: Word32
871
--       out = (xorShifted `shiftR` (fromIntegral rot)) .|. (xorShifted `shiftL` fromIntegral ((-rot) .&. 31))
872
--       in (out, PCGen newState inc)
873
-- :}
874
--
875
-- >>> fst $ stepGen $ snd $ stepGen (PCGen 17 29)
876
-- 3288430965
877
--
878
-- You can make it an instance of 'RandomGen' as follows:
879
--
880
-- >>> :{
881
-- instance RandomGen PCGen where
882
--   genWord32 = stepGen
883
--   split _ = error "PCG is not splittable"
884
-- :}
885
--
886
--
887
-- === How to implement 'RandomGen' for a pseudo-random number generator without a power-of-2 modulus
888
--
889
-- __We do not recommend you implement any new pseudo-random number generators without a power-of-2 modulus.__
890
--
891
-- Pseudo-random number generators without a power-of-2 modulus perform
892
-- /significantly worse/ than pseudo-random number generators with a power-of-2
893
-- modulus with this library. This is because most functionality in this
894
-- library is based on generating and transforming uniformly pseudo-random
895
-- machine words, and generating uniformly pseudo-random machine words using a
896
-- pseudo-random number generator without a power-of-2 modulus is expensive.
897
--
898
-- The pseudo-random number generator from
899
-- <https://dl.acm.org/doi/abs/10.1145/62959.62969 L’Ecuyer (1988)> natively
900
-- generates an integer value in the range @[1, 2147483562]@. This is the
901
-- generator used by this library before it was replaced by SplitMix in version
902
-- 1.2.
903
--
904
-- >>> data LegacyGen = LegacyGen !Int32 !Int32
905
-- >>> :{
906
-- let legacyNext :: LegacyGen -> (Int, LegacyGen)
907
--     legacyNext (LegacyGen s1 s2) = (fromIntegral z', LegacyGen s1'' s2'') where
908
--       z' = if z < 1 then z + 2147483562 else z
909
--       z = s1'' - s2''
910
--       k = s1 `quot` 53668
911
--       s1'  = 40014 * (s1 - k * 53668) - k * 12211
912
--       s1'' = if s1' < 0 then s1' + 2147483563 else s1'
913
--       k' = s2 `quot` 52774
914
--       s2' = 40692 * (s2 - k' * 52774) - k' * 3791
915
--       s2'' = if s2' < 0 then s2' + 2147483399 else s2'
916
-- :}
917
--
918
-- You can make it an instance of 'RandomGen' as follows:
919
--
920
-- >>> :{
921
-- instance RandomGen LegacyGen where
922
--   next = legacyNext
923
--   genRange _ = (1, 2147483562)
924
--   split _ = error "Not implemented"
925
-- :}
926

927
-- $deprecations
928
--
929
-- Version 1.2 mostly maintains backwards compatibility with version 1.1. This
930
-- has a few consequences users should be aware of:
931
--
932
-- *   The type class 'Random' is only provided for backwards compatibility.
933
--     New code should use 'Uniform' and 'UniformRange' instead.
934
--
935
-- *   The methods 'next' and 'genRange' in 'RandomGen' are deprecated and only
936
--     provided for backwards compatibility. New instances of 'RandomGen' should
937
--     implement word-based methods instead. See below for more information
938
--     about how to write a 'RandomGen' instance.
939
--
940
-- *   This library provides instances for 'Random' for some unbounded types
941
--     for backwards compatibility. For an unbounded type, there is no way
942
--     to generate a value with uniform probability out of its entire domain, so
943
--     the 'random' implementation for unbounded types actually generates a
944
--     value based on some fixed range.
945
--
946
--     For 'Integer', 'random' generates a value in the 'Int' range. For 'Float'
947
--     and 'Double', 'random' generates a floating point value in the range @[0,
948
--     1)@.
949
--
950
--     This library does not provide 'Uniform' instances for any unbounded
951
--     types.
952

953
-- $reproducibility
954
--
955
-- If you have two builds of a particular piece of code against this library,
956
-- any deterministic function call should give the same result in the two
957
-- builds if the builds are
958
--
959
-- *   compiled against the same major version of this library
960
-- *   on the same architecture (32-bit or 64-bit)
961

962
-- $references
963
--
964
-- 1. Guy L. Steele, Jr., Doug Lea, and Christine H. Flood. 2014. Fast
965
-- splittable pseudorandom number generators. In Proceedings of the 2014 ACM
966
-- International Conference on Object Oriented Programming Systems Languages &
967
-- Applications (OOPSLA '14). ACM, New York, NY, USA, 453-472. DOI:
968
-- <https://doi.org/10.1145/2660193.2660195>
969

970
-- $setup
971
--
972
-- >>> import Control.Monad (replicateM)
973
-- >>> import Data.List (unfoldr)
974
-- >>> setStdGen (mkStdGen 0)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc