module Fake.Types where

------------------------------------------------------------------------------
import Control.Monad
import System.Random
------------------------------------------------------------------------------

newtype FGen a = MkFGen { FGen a -> StdGen -> a
unFGen :: StdGen -> a }

instance Functor FGen where
  fmap :: (a -> b) -> FGen a -> FGen b
fmap a -> b
f (MkFGen StdGen -> a
h) =
    (StdGen -> b) -> FGen b
forall a. (StdGen -> a) -> FGen a
MkFGen (\StdGen
r -> a -> b
f (StdGen -> a
h StdGen
r))

instance Applicative FGen where
  pure :: a -> FGen a
pure  = a -> FGen a
forall (m :: * -> *) a. Monad m => a -> m a
return
  <*> :: FGen (a -> b) -> FGen a -> FGen b
(<*>) = FGen (a -> b) -> FGen a -> FGen b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

instance Monad FGen where
  return :: a -> FGen a
return a
x =
    (StdGen -> a) -> FGen a
forall a. (StdGen -> a) -> FGen a
MkFGen (\StdGen
_ -> a
x)

  MkFGen StdGen -> a
m >>= :: FGen a -> (a -> FGen b) -> FGen b
>>= a -> FGen b
k =
    (StdGen -> b) -> FGen b
forall a. (StdGen -> a) -> FGen a
MkFGen (\StdGen
r ->
      let (StdGen
r1,StdGen
r2)  = StdGen -> (StdGen, StdGen)
forall g. RandomGen g => g -> (g, g)
split StdGen
r
          MkFGen StdGen -> b
m' = a -> FGen b
k (StdGen -> a
m StdGen
r1)
       in StdGen -> b
m' StdGen
r2
    )


------------------------------------------------------------------------------
-- | Run a generator to generate a random value in the IO monad.
generate :: FGen a -> IO a
generate :: FGen a -> IO a
generate (MkFGen StdGen -> a
g) = do
    StdGen
r <- IO StdGen
forall (m :: * -> *). MonadIO m => m StdGen
newStdGen
    a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (StdGen -> a
g StdGen
r)