    module Foundation.Random.Class
        ( MonadRandom(..)
        ) where

    import           Data.Proxy
    import           Basement.Imports
    import           Foundation.System.Entropy
    import qualified Basement.UArray as A

    -- | A monad constraint that allows to generate random bytes
    class (Functor m, Applicative m, Monad m) => MonadRandom m where
        getRandomBytes :: CountOf Word8 -> m (UArray Word8)
        getRandomWord64 :: m Word64
        getRandomF32 :: m Float
        getRandomF64 :: m Double

    instance MonadRandom IO where
        getRandomBytes :: CountOf Word8 -> IO (UArray Word8)
    getRandomBytes  = CountOf Word8 -> IO (UArray Word8)
    getEntropy
        getRandomWord64 :: IO Word64
    getRandomWord64 = (UArray Word64 -> Offset Word64 -> Word64)
    -> Offset Word64 -> UArray Word64 -> Word64
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip UArray Word64 -> Offset Word64 -> Word64
    forall ty. PrimType ty => UArray ty -> Offset ty -> ty
    A.index 0 (UArray Word64 -> Word64)
    -> (UArray Word8 -> UArray Word64) -> UArray Word8 -> Word64
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . UArray Word8 -> UArray Word64
    forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
    A.unsafeRecast
                      (UArray Word8 -> Word64) -> IO (UArray Word8) -> IO Word64
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CountOf Word8 -> IO (UArray Word8)
    forall (m :: * -> *).
    MonadRandom m =>
    CountOf Word8 -> m (UArray Word8)
    getRandomBytes (Proxy Word64 -> CountOf Word8
    forall ty. PrimType ty => Proxy ty -> CountOf Word8
    A.primSizeInBytes (Proxy Word64
    forall k (t :: k). Proxy t
    Proxy :: Proxy Word64))
        getRandomF32 :: IO Float
    getRandomF32 = (UArray Float -> Offset Float -> Float)
    -> Offset Float -> UArray Float -> Float
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip UArray Float -> Offset Float -> Float
    forall ty. PrimType ty => UArray ty -> Offset ty -> ty
    A.index 0 (UArray Float -> Float)
    -> (UArray Word8 -> UArray Float) -> UArray Word8 -> Float
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . UArray Word8 -> UArray Float
    forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
    A.unsafeRecast
                      (UArray Word8 -> Float) -> IO (UArray Word8) -> IO Float
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CountOf Word8 -> IO (UArray Word8)
    forall (m :: * -> *).
    MonadRandom m =>
    CountOf Word8 -> m (UArray Word8)
    getRandomBytes (Proxy Word64 -> CountOf Word8
    forall ty. PrimType ty => Proxy ty -> CountOf Word8
    A.primSizeInBytes (Proxy Word64
    forall k (t :: k). Proxy t
    Proxy :: Proxy Word64))
        getRandomF64 :: IO Double
    getRandomF64 = (UArray Double -> Offset Double -> Double)
    -> Offset Double -> UArray Double -> Double
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip UArray Double -> Offset Double -> Double
    forall ty. PrimType ty => UArray ty -> Offset ty -> ty
    A.index 0 (UArray Double -> Double)
    -> (UArray Word8 -> UArray Double) -> UArray Word8 -> Double
    forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . UArray Word8 -> UArray Double
    forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
    A.unsafeRecast
                      (UArray Word8 -> Double) -> IO (UArray Word8) -> IO Double
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CountOf Word8 -> IO (UArray Word8)
    forall (m :: * -> *).
    MonadRandom m =>
    CountOf Word8 -> m (UArray Word8)
    getRandomBytes (Proxy Word64 -> CountOf Word8
    forall ty. PrimType ty => Proxy ty -> CountOf Word8
    A.primSizeInBytes (Proxy Word64
    forall k (t :: k). Proxy t
    Proxy :: Proxy Word64))