-- |
-- Module : Crypto.Random.Types
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- 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