-- | -- Module : Crypto.Random.Types -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.Random.Types ( MonadRandom(..) , MonadPseudoRandom , DRG(..) , withDRG ) where import Crypto.Random.Entropy import Crypto.Internal.ByteArray import Crypto.Internal.Imports -- | A monad constraint that allows to generate random bytes class (Functor m, Monad m) => MonadRandom m where getRandomBytes :: ByteArray byteArray => Int -> m byteArray -- | A Deterministic Random Generator (DRG) class class DRG gen where -- | Generate N bytes of randomness from a DRG randomBytesGenerate :: ByteArray byteArray => Int -> gen -> (byteArray, gen) instance MonadRandom IO where getRandomBytes = getEntropy -- | A simple Monad class very similar to a State Monad -- with the state being a DRG. newtype MonadPseudoRandom gen a = MonadPseudoRandom { runPseudoRandom :: gen -> (a, gen) } instance DRG gen => Functor (MonadPseudoRandom gen) where fmap f m = MonadPseudoRandom $ \g1 -> let (a, g2) = runPseudoRandom m g1 in (f a, g2) instance DRG gen => Applicative (MonadPseudoRandom gen) where pure a = MonadPseudoRandom $ \g -> (a, g) (<*>) fm m = MonadPseudoRandom $ \g1 -> let (f, g2) = runPseudoRandom fm g1 (a, g3) = runPseudoRandom m g2 in (f a, g3) instance DRG gen => Monad (MonadPseudoRandom gen) where return a = MonadPseudoRandom $ \g -> (a, g) (>>=) m1 m2 = MonadPseudoRandom $ \g1 -> let (a, g2) = runPseudoRandom m1 g1 in runPseudoRandom (m2 a) g2 instance DRG gen => MonadRandom (MonadPseudoRandom gen) where getRandomBytes n = MonadPseudoRandom (randomBytesGenerate n) -- | Run a pure computation with a Deterministic Random Generator -- in the 'MonadPseudoRandom' withDRG :: DRG gen => gen -> MonadPseudoRandom gen a -> (a, gen) withDRG gen m = runPseudoRandom m gen