+import Control.Monad (ap)

import Control.Monad.ST (ST, runST)

import Data.Bits ((.&.), (.|.))

import Data.Time.Clock.POSIX (getPOSIXTime)

import Data.Ratio ((%), numerator)

--- | Generate a single uniformly distributed random variate. The

--- range of values produced varies by type:

--- * For fixed-width integral types, the type's entire range is used.

--- * For floating point numbers, the range (0,1] is used. Zero is

--- explicitly excluded, to allow variates to be used in statistical

--- calculations that require non-zero values.

--- * The range of random 'Integer' values is the same as for 'Int'.

+-- | The class of types for which we can generate random variates.

+ -- | Generate a single uniformly distributed random variate. The

+ -- range of values produced varies by type:

+ -- * For fixed-width integral types, the type's entire range is

+ -- * For floating point numbers, the range (0,1] is used. Zero is

+ -- explicitly excluded, to allow variates to be used in

+ -- statistical calculations that require non-zero values.

+ -- * The range of random 'Integer' values is the same as for

uniform :: Gen s -> ST s a

-- Thanks to Duncan Coutts for finding the pattern below for

+instance (Variate a, Variate b) => Variate (a,b) where

+ uniform = f where f g = (,) `fmap` uniform g `ap` uniform g

+instance (Variate a, Variate b, Variate c) => Variate (a,b,c) where

+ uniform = f where f g = (,,) `fmap` uniform g `ap` uniform g `ap` uniform g

+instance (Variate a, Variate b, Variate c, Variate d) => Variate (a,b,c,d) where

+ where f g = (,,,) `fmap` uniform g `ap` uniform g `ap` uniform g

wordsTo64Bit :: Integral a => Word32 -> Word32 -> a

fromIntegral ((fromIntegral a `shiftL` 32) .|. fromIntegral b)