{-# LANGUAGE GADTs #-} -- | Random variables in uniform and exponential distributions, with interleaving. -- -- @since 1.0 module Control.Effect.Random ( -- * Random effect Random(..) , uniform , uniformR , interleave -- * Non-uniform distributions , exponential -- * Re-exports , Algebra , Has , run ) where import Control.Algebra import qualified System.Random as R (Random(..)) -- | Uniformly-distributed random variables, with interleaving. -- -- @since 1.0 data Random m k where Uniform :: R.Random a => Random m a UniformR :: R.Random a => (a, a) -> Random m a Interleave :: m a -> Random m a -- | Produce a random variable uniformly distributed in a range determined by its type’s 'R.Random' instance. For example: -- -- * bounded types (instances of 'Bounded', such as 'Char') typically sample all of the constructors. -- * fractional types, the range is normally the semi-closed interval [0,1). -- * for 'Integer', the range is (arbitrarily) the range of 'Int'. -- -- @since 1.1 uniform :: (R.Random a, Has Random sig m) => m a uniform = send Uniform {-# INLINE uniform #-} -- | Produce a random variable uniformly distributed in the given range. -- -- @ -- 'Data.Ix.inRange' (a, b) '<$>' 'uniformR' (a, b) = 'pure' 'True' -- @ -- -- @since 1.1 uniformR :: (R.Random a, Has Random sig m) => (a, a) -> m a uniformR interval = send (UniformR interval) {-# INLINE uniformR #-} -- | Run a computation by splitting the generator, using one half for the passed computation and the other for the continuation. -- -- @ -- 'interleave' ('pure' a) = 'pure' a -- @ -- -- @since 1.0 interleave :: Has Random sig m => m a -> m a interleave m = send (Interleave m) {-# INLINE interleave #-} -- * Non-uniform distributions -- | Produce a random variable in an expnoential distribution with the given scale. -- -- @since 1.1 exponential :: (R.Random a, Floating a, Has Random sig m) => a -> m a exponential a = do x <- uniform pure $! -log x / a {-# INLINE exponential #-}