-- | 'Arbitrary' operations that respect Graphula's seed
module Graphula.Arbitrary
  ( generate
  ) where

import Prelude

import Control.Monad.IO.Unlift (MonadIO, liftIO)
import Data.IORef (readIORef, writeIORef)
import Graphula.Class (MonadGraphulaBackend, askGen)
import System.Random (split)
import Test.QuickCheck (Gen)
import Test.QuickCheck.Gen (unGen)

-- | Run a generator
--
-- This is akin to 'Test.QuickCheck.generate', but utilizing graphula's
-- generation. The size passed to the generator is always 30; if you want
-- another size then you should explicitly use 'Test.QuickCheck.resize'.
--
generate :: (MonadIO m, MonadGraphulaBackend m) => Gen a -> m a
generate :: Gen a -> m a
generate Gen a
gen = do
  IORef QCGen
genRef <- m (IORef QCGen)
forall (m :: * -> *). MonadGraphulaBackend m => m (IORef QCGen)
askGen
  QCGen
g <- IO QCGen -> m QCGen
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO QCGen -> m QCGen) -> IO QCGen -> m QCGen
forall a b. (a -> b) -> a -> b
$ IORef QCGen -> IO QCGen
forall a. IORef a -> IO a
readIORef IORef QCGen
genRef
  let
    (QCGen
g1, QCGen
g2) = QCGen -> (QCGen, QCGen)
forall g. RandomGen g => g -> (g, g)
split QCGen
g
    x :: a
x = Gen a -> QCGen -> Int -> a
forall a. Gen a -> QCGen -> Int -> a
unGen Gen a
gen QCGen
g1 Int
30
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef QCGen -> QCGen -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef QCGen
genRef QCGen
g2
  a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x