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

haskell / random / 429

05 Jul 2025 06:41PM UTC coverage: 69.035% (+0.3%) from 68.696%
429

push

github

web-flow
Merge 4e091cbf2 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
  RandomGen g =>
486
  -- | E.g. @(:)@ but subject to fusion
487
  (a -> as -> as) ->
488
  -- | E.g. 'random'
489
  (g -> (a, g)) ->
490
  -- | A 'RandomGen' instance
491
  g ->
492
  as
493
buildRandoms cons rand = go
2✔
494
  where
495
    -- The seq fixes part of #4218 and also makes fused Core simpler:
496
    -- https://gitlab.haskell.org/ghc/ghc/-/issues/4218
497
    go g = x `seq` (x `cons` go g') where (x, g') = rand g
2✔
498

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

504
instance Random Int8
505

506
instance Random Int16
507

508
instance Random Int32
509

510
instance Random Int64
511

512
instance Random Int
513

514
instance Random Word
515

516
instance Random Word8
517

518
instance Random Word16
519

520
instance Random Word32
521

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

528
instance Random CSChar
529

530
instance Random CUChar
531

532
instance Random CShort
533

534
instance Random CUShort
535

536
instance Random CInt
537

538
instance Random CUInt
539

540
instance Random CLong
541

542
instance Random CULong
543

544
instance Random CPtrdiff
545

546
instance Random CSize
547

548
instance Random CWchar
549

550
instance Random CSigAtomic
551

552
instance Random CLLong
553

554
instance Random CULLong
555

556
instance Random CIntPtr
557

558
instance Random CUIntPtr
559

560
instance Random CIntMax
561

562
instance Random CUIntMax
563

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

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

578
instance Random Char
579

580
instance Random Bool
581

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

835
-------------------------------------------------------------------------------
836
-- Notes
837
-------------------------------------------------------------------------------
838

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

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

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

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

971
-- $setup
972
--
973
-- >>> import Control.Monad (replicateM)
974
-- >>> import Data.List (unfoldr)
975
-- >>> 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