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 = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall ty. PrimType ty => UArray ty -> Offset ty -> ty
A.index Offset Word64
0 forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast
                  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *).
MonadRandom m =>
CountOf Word8 -> m (UArray Word8)
getRandomBytes (forall ty. PrimType ty => Proxy ty -> CountOf Word8
A.primSizeInBytes (forall {k} (t :: k). Proxy t
Proxy :: Proxy Word64))
    getRandomF32 :: IO Float
getRandomF32 = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall ty. PrimType ty => UArray ty -> Offset ty -> ty
A.index Offset Float
0 forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast
                  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *).
MonadRandom m =>
CountOf Word8 -> m (UArray Word8)
getRandomBytes (forall ty. PrimType ty => Proxy ty -> CountOf Word8
A.primSizeInBytes (forall {k} (t :: k). Proxy t
Proxy :: Proxy Word64))
    getRandomF64 :: IO Double
getRandomF64 = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall ty. PrimType ty => UArray ty -> Offset ty -> ty
A.index Offset Double
0 forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast
                  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *).
MonadRandom m =>
CountOf Word8 -> m (UArray Word8)
getRandomBytes (forall ty. PrimType ty => Proxy ty -> CountOf Word8
A.primSizeInBytes (forall {k} (t :: k). Proxy t
Proxy :: Proxy Word64))