    -- |Flexible modeling and sampling of random variables.
    --
    -- The central abstraction in this library is the concept of a random
    -- variable.  It is not fully formalized in the standard measure-theoretic
    -- language, but rather is informally defined as a \"thing you can get random
    -- values out of\".  Different random variables may have different types of
    -- values they can return or the same types but different probabilities for
    -- each value they can return.  The random values you get out of them are
    -- traditionally called \"random variates\".
    --
    -- Most imperative-language random number libraries are all about obtaining
    -- and manipulating random variates.  This one is about defining, manipulating
    -- and sampling random variables.  Computationally, the distinction is small
    -- and mostly just a matter of perspective, but from a program design
    -- perspective it provides both a powerfully composable abstraction and a
    -- very useful separation of concerns.
    --
    -- Abstract random variables as implemented by 'RVar' are composable.  They can
    -- be defined in a monadic / \"imperative\" style that amounts to manipulating
    -- variates, but with strict type-level isolation.  Concrete random variables
    -- are also provided, but they do not compose as generically.  The 'Distribution'
    -- type class allows concrete random variables to \"forget\" their concreteness
    -- so that they can be composed.  For examples of both, see the documentation
    -- for 'RVar' and 'Distribution', as well as the code for any of the concrete
    -- distributions such as 'Uniform', 'Gamma', etc.
    --
    -- Both abstract and concrete random variables can be sampled (despite the
    -- types GHCi may list for the functions) by the functions in "Data.Random.Sample".
    --
    -- Random variable sampling is done with regard to a generic basis of primitive
    -- random variables defined in "Data.Random.Internal.Primitives".  This basis
    -- is very low-level and the actual set of primitives is still fairly experimental,
    -- which is why it is in the \"Internal\" sub-heirarchy.  User-defined variables
    -- should use the existing high-level variables such as 'Uniform' and 'Normal'
    -- rather than these basis variables.  "Data.Random.Source" defines classes for
    -- entropy sources that provide implementations of these primitive variables.
    -- Several implementations are available in the Data.Random.Source.* modules.
    module Data.Random
        ( -- * Random variables
          -- ** Abstract ('RVar')
          RVar, RVarT,
          runRVar, runRVarT, runRVarTWith,

          -- ** Concrete ('Distribution')
          Distribution(..), CDF(..), PDF(..),

          -- * Sampling random variables
          Sampleable(..), sample, sampleState, samplePure,

          -- * A few very common distributions
          Uniform(..), uniform, uniformT,
          StdUniform(..), stdUniform, stdUniformT,
          Normal(..), normal, stdNormal, normalT, stdNormalT,
          Gamma(..), gamma, gammaT,

          -- * Entropy Sources
          StatefulGen, RandomGen,

          -- * Useful list-based operations
          randomElement,
          shuffle, shuffleN, shuffleNofM

        ) where

    import Data.Random.Sample
    import Data.Random.Distribution
    import Data.Random.Distribution.Gamma
    import Data.Random.Distribution.Normal
    import Data.Random.Distribution.Uniform

    import Data.Random.Lift ()
    import Data.Random.List
    import Data.Random.RVar

    import System.Random.Stateful (StatefulGen, RandomGen)