module Test.QuickCheck.GenT.Private where

import qualified Test.QuickCheck.Random as QC
import qualified System.Random as Random

import Control.Monad.Trans.Class (MonadTrans, lift)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad (ap)


newtype GenT m a = GenT { forall (m :: * -> *) a. GenT m a -> QCGen -> Int -> m a
unGenT :: QC.QCGen -> Int -> m a }

instance (Functor m) => Functor (GenT m) where
  fmap :: forall a b. (a -> b) -> GenT m a -> GenT m b
fmap a -> b
f GenT m a
m = forall (m :: * -> *) a. (QCGen -> Int -> m a) -> GenT m a
GenT forall a b. (a -> b) -> a -> b
$ \QCGen
r Int
n -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. GenT m a -> QCGen -> Int -> m a
unGenT GenT m a
m QCGen
r Int
n

instance (Monad m) => Monad (GenT m) where
  return :: forall a. a -> GenT m a
return a
a = forall (m :: * -> *) a. (QCGen -> Int -> m a) -> GenT m a
GenT (\QCGen
_ Int
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return a
a)
  GenT m a
m >>= :: forall a b. GenT m a -> (a -> GenT m b) -> GenT m b
>>= a -> GenT m b
k = forall (m :: * -> *) a. (QCGen -> Int -> m a) -> GenT m a
GenT forall a b. (a -> b) -> a -> b
$ \QCGen
r Int
n -> do
    let (QCGen
r1, QCGen
r2) = forall g. RandomGen g => g -> (g, g)
Random.split QCGen
r
    a
a <- forall (m :: * -> *) a. GenT m a -> QCGen -> Int -> m a
unGenT GenT m a
m QCGen
r1 Int
n
    forall (m :: * -> *) a. GenT m a -> QCGen -> Int -> m a
unGenT (a -> GenT m b
k a
a) QCGen
r2 Int
n

instance (MonadFail m) => MonadFail (GenT m) where
  fail :: forall a. String -> GenT m a
fail String
msg = forall (m :: * -> *) a. (QCGen -> Int -> m a) -> GenT m a
GenT (\QCGen
_ Int
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
msg)

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

instance MonadTrans GenT where
  lift :: forall (m :: * -> *) a. Monad m => m a -> GenT m a
lift m a
m = forall (m :: * -> *) a. (QCGen -> Int -> m a) -> GenT m a
GenT (\QCGen
_ Int
_ -> m a
m)

instance (MonadIO m) => MonadIO (GenT m) where
  liftIO :: forall a. IO a -> GenT m a
liftIO = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO