-- | '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 :: forall (m :: * -> *) a.
(MonadIO m, MonadGraphulaBackend m) =>
Gen a -> m a
generate Gen a
gen = do
  IORef QCGen
genRef <- forall (m :: * -> *). MonadGraphulaBackend m => m (IORef QCGen)
askGen
  QCGen
g <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. IORef a -> IO a
readIORef IORef QCGen
genRef
  let
    (QCGen
g1, QCGen
g2) = forall g. RandomGen g => g -> (g, g)
split QCGen
g
    x :: a
x = forall a. Gen a -> QCGen -> Int -> a
unGen Gen a
gen QCGen
g1 Int
30
  forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall a. IORef a -> a -> IO ()
writeIORef IORef QCGen
genRef QCGen
g2
  forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x