{-# LANGUAGE GADTs, RankNTypes, DeriveDataTypeable #-}
-- |This is an internal interface to support the 'RVar' abstraction.  It
-- reifies the operations provided by both MonadRandom and RandomSource in a
-- uniform and efficient way, as functions of type @Prim a -> m a@.
module Data.Random.Source.Internal.Prim (Prim(..)) where

import Data.Word
import Data.Typeable

-- |A 'Prompt' GADT describing a request for a primitive random variate.
-- Random variable definitions will request their entropy via these prompts,
-- and entropy sources will satisfy those requests.  The functions in
-- "Data.Random.Source.Internal.TH" extend incomplete entropy-source definitions
-- to complete ones, essentially defining a very flexible 
-- implementation-defaulting system.
-- 
-- Some possible future additions:
--    PrimFloat :: Prim Float
--    PrimInt :: Prim Int
--    PrimPair :: Prim a -> Prim b -> Prim (a :*: b)
--    PrimNormal :: Prim Double
--    PrimChoice :: [(Double :*: a)] -> Prim a
--    PrimBytes  :: !Int -> Prim ByteString
--
-- Unfortunately, I cannot get Haddock to accept my comments about the 
-- data constructors, but hopefully they should be reasonably self-explanatory.
data Prim a where
    -- An unsigned byte, uniformly distributed from 0 to 0xff
    PrimWord8           :: Prim Word8
    -- An unsigned 16-bit word, uniformly distributed from 0 to 0xffff
    PrimWord16          :: Prim Word16
    -- An unsigned 32-bit word, uniformly distributed from 0 to 0xffffffff
    PrimWord32          :: Prim Word32
    -- An unsigned 64-bit word, uniformly distributed from 0 to 0xffffffffffffffff
    PrimWord64          :: Prim Word64
    -- A double-precision float U, uniformly distributed 0 <= U < 1
    PrimDouble          :: Prim Double
    -- A uniformly distributed 'Integer' 0 <= U < 256^n
    PrimNByteInteger    :: !Int -> Prim Integer
    deriving (Typeable)

instance Show (Prim a) where
    showsPrec :: Int -> Prim a -> ShowS
showsPrec Int
_p Prim a
PrimWord8               = String -> ShowS
showString String
"PrimWord8"
    showsPrec Int
_p Prim a
PrimWord16              = String -> ShowS
showString String
"PrimWord16"
    showsPrec Int
_p Prim a
PrimWord32              = String -> ShowS
showString String
"PrimWord32"
    showsPrec Int
_p Prim a
PrimWord64              = String -> ShowS
showString String
"PrimWord64"
    showsPrec Int
_p Prim a
PrimDouble              = String -> ShowS
showString String
"PrimDouble"
    showsPrec  Int
p (PrimNByteInteger Int
n)    = Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (String -> ShowS
showString String
"PrimNByteInteger " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 Int
n)