@@ -69,6 +69,9 @@ import GHC.Stack
6969import System.Random
7070import Test.QuickCheck hiding (Args , Fun )
7171import Test.QuickCheck.Gen
72+ import Test.QuickCheck.Random
73+ import Control.Arrow (second )
74+ import Control.Monad.Trans
7275
7376-- ==============================================================
7477-- The GE Monad
@@ -90,6 +93,39 @@ instance Monad GE where
9093 GenError es >>= _ = GenError es
9194 Result a >>= k = k a
9295
96+ ------------------------------------------------------------------------
97+ -- Strict gen monad
98+ ------------------------------------------------------------------------
99+
100+ liftGenToStrict :: Gen a -> StrictGenT m a
101+ liftGenToStrict g = StrictGen $ \ seed size -> do
102+ let (seed', seed'') = split seed
103+ pure (seed'', unGen g seed' size)
104+
105+ runStrictGen :: StrictGenT m a -> Gen (m a )
106+ runStrictGen g = MkGen $ \ seed size -> do
107+ snd <$> unStrictGen g seed size
108+
109+ strictGetSize :: StrictGenT m Int
110+ strictGetSize = StrictGen $ \ seed size -> pure (seed, size)
111+
112+ newtype StrictGenT m a = StrictGen { unStrictGen :: QCGen -> Int -> m (QCGen , a ) }
113+
114+ instance Functor (StrictGenT m ) where
115+ fmap f (StrictGen g) = StrictGen $ \ seed size -> second f <$> g seed size
116+
117+ instance Applicative (StrictGenT m ) where
118+ pure a = StrictGen $ \ seed _ -> pure (seed, a)
119+ (<*>) = ap
120+
121+ instance Monad (StrictGenT m ) where
122+ StrictGen g >>= k = StrictGen $ \ seed size -> do
123+ (seed', a) <- g seed size
124+ unStrictGen (k a) seed' size
125+
126+ instance MonadTrans StrictGenT where
127+ lift m = StrictGen $ \ seed _ -> (seed,) <$> m
128+
93129------------------------------------------------------------------------
94130-- The GenT monad
95131-- An environment monad on top of GE
@@ -108,19 +144,17 @@ data GenMode
108144
109145-- | A `Gen` monad wrapper that allows different generation modes and different
110146-- failure types.
111- newtype GenT m a = GenT { runGenT :: GenMode -> [NonEmpty String ] -> Gen ( m a ) }
147+ newtype GenT m a = GenT { runGenT :: GenMode -> [NonEmpty String ] -> StrictGenT m a }
112148 deriving (Functor )
113149
114150instance Monad m => Applicative (GenT m ) where
115- pure a = GenT (\ _ _ -> pure @ Gen ( pure @ m a) )
151+ pure a = GenT (\ _ _ -> pure a )
116152 (<*>) = ap
117153
118- -- I think this might be an inlined use of the Gen monad transformer?
119154instance Monad m => Monad (GenT m ) where
120- GenT m >>= k = GenT $ \ mode -> \ msgs -> MkGen $ \ r n -> do
121- let (r1, r2) = split r
122- a <- unGen (m mode msgs) r1 n
123- unGen (runGenT (k a) mode msgs) r2 n
155+ GenT m >>= k = GenT $ \ mode msgs -> do
156+ a <- m mode msgs
157+ runGenT (k a) mode msgs
124158
125159instance MonadGenError m => MonadFail (GenT m ) where
126160 fail s = genError s
@@ -168,15 +202,15 @@ instance MonadGenError GE where
168202
169203-- | calls to genError and fatalError, add the stacked messages in the monad.
170204instance MonadGenError m => MonadGenError (GenT m ) where
171- genErrorNE e = GenT $ \ _ xs -> pure $ genErrors (add e xs)
172- genErrors es = GenT $ \ _ xs -> pure $ genErrors (cat es xs)
205+ genErrorNE e = GenT $ \ _ xs -> lift $ genErrors (add e xs)
206+ genErrors es = GenT $ \ _ xs -> lift $ genErrors (cat es xs)
173207
174208 -- Perhaps we want to turn genError into fatalError, if mode_ is Strict?
175- fatalErrorNE e = GenT $ \ _ xs -> pure $ fatalErrors (add e xs)
176- fatalErrors es = GenT $ \ _ xs -> pure $ fatalErrors (cat es xs)
209+ fatalErrorNE e = GenT $ \ _ xs -> lift $ fatalErrors (add e xs)
210+ fatalErrors es = GenT $ \ _ xs -> lift $ fatalErrors (cat es xs)
177211
178212 -- Perhaps we want to turn fatalError into genError, if mode_ is Loose?
179- explainNE e (GenT f) = GenT $ \ mode es -> fmap ( explainNE e) ( f mode es)
213+ explainNE e (GenT f) = GenT $ \ mode es -> explainNE e $ f mode es
180214
181215-- ====================================================
182216-- useful operations on NonEmpty
@@ -271,28 +305,24 @@ listFromGE = fromGE (const []) . explain "listFromGE"
271305
272306-- | Run a t`GenT` generator in `Strict` mode
273307strictGen :: GenT m a -> Gen (m a )
274- strictGen genT = runGenT genT Strict []
308+ strictGen genT = runStrictGen $ runGenT genT Strict []
275309
276310-- | Run a t`GenT` generator in `Loose` mode
277311looseGen :: GenT m a -> Gen (m a )
278- looseGen genT = runGenT genT Loose []
312+ looseGen genT = runStrictGen $ runGenT genT Loose []
279313
280314-- | Turn a t`GenT` generator into a `Gen` generator in `Strict` mode
281315genFromGenT :: GenT GE a -> Gen a
282316genFromGenT genT = errorGE <$> strictGen genT
283317
284- -- | Locally change the generation size
285- resizeT :: (Int -> Int ) -> GenT m a -> GenT m a
286- resizeT f (GenT gm) = GenT $ \ mode msgs -> sized $ \ sz -> resize (f sz) (gm mode msgs)
287-
288318-- | Turn a `Gen` generator into a t`GenT` generator that never fails.
289319pureGen :: Applicative m => Gen a -> GenT m a
290- pureGen gen = GenT $ \ _ _ -> pure <$> gen
320+ pureGen gen = GenT $ \ _ _ -> liftGenToStrict gen
291321
292322-- | Lift `listOf` to t`GenT`
293323listOfT :: MonadGenError m => GenT GE a -> GenT m [a ]
294324listOfT gen = do
295- lst <- pureGen . listOf $ runGenT gen Loose []
325+ lst <- pureGen . listOf $ runStrictGen $ runGenT gen Loose []
296326 catGEs lst
297327
298328-- | Generate a list of elements of length at most @goalLen@, but accepting
@@ -310,18 +340,18 @@ listOfUntilLenT gen goalLen validLen =
310340 genList `suchThatT` validLen . length
311341 where
312342 genList = do
313- res <- pureGen . vectorOf goalLen $ runGenT gen Loose []
343+ res <- pureGen . vectorOf goalLen $ runStrictGen $ runGenT gen Loose []
314344 catGEs res
315345
316346-- | Lift `vectorOf` to t`GenT`
317347vectorOfT :: MonadGenError m => Int -> GenT GE a -> GenT m [a ]
318348vectorOfT i gen = GenT $ \ mode _ -> do
319- res <- fmap sequence . vectorOf i $ runGenT gen Strict []
349+ res <- _ -- pureGen $ fmap sequence . vectorOf i $ runStrictGen $ runGenT gen Strict []
320350 case mode of
321- Strict -> pure $ runGE res
351+ Strict -> lift $ runGE res
322352 Loose -> case res of
323- FatalError es -> pure $ genErrors es
324- _ -> pure $ runGE res
353+ FatalError es -> lift $ genErrors es
354+ _ -> lift $ runGE res
325355
326356infixl 2 `suchThatT`
327357
@@ -356,11 +386,11 @@ scaleT sc (GenT gen) = GenT $ \mode msgs -> scale sc $ gen mode msgs
356386-- | Access the `GenMode` we are running in, useful to decide e.g. if we want
357387-- to re-try in case of a `GenError` or give up
358388getMode :: Applicative m => GenT m GenMode
359- getMode = GenT $ \ mode _ -> pure ( pure mode)
389+ getMode = GenT $ \ mode _ -> pure mode
360390
361391-- | Get the current stack of `explain` above you
362392getMessages :: Applicative m => GenT m [NonEmpty String ]
363- getMessages = GenT $ \ _ msgs -> pure ( pure msgs)
393+ getMessages = GenT $ \ _ msgs -> pure msgs
364394
365395-- | Locally change the generation mode
366396withMode :: GenMode -> GenT m a -> GenT m a
@@ -377,7 +407,7 @@ frequencyT gs = do
377407 msgs <- getMessages
378408 r <-
379409 explain " suchThatT in oneofT" $
380- pureGen (frequency [(f, runGenT g mode msgs) | (f, g) <- gs]) `suchThatT` isOk
410+ pureGen (frequency [(f, runStrictGen $ runGenT g mode msgs) | (f, g) <- gs]) `suchThatT` isOk
381411 runGE r
382412
383413-- | Lift `choose` to t`GenT`, failing with a `genError` in case of an empty interval
@@ -388,18 +418,16 @@ chooseT (a, b)
388418
389419-- | Get the size provided to the generator
390420sizeT :: Monad m => GenT m Int
391- sizeT = GenT $ \ mode msgs -> sized $ \ n -> runGenT ( pure n) mode msgs
421+ sizeT = GenT $ \ mode msgs -> strictGetSize
392422
393423-- ==================================================================
394424-- Reflective analysis of the internal GE structure of (GenT GE x)
395425-- This allows "catching" internal FatalError and GenError, and allowing
396426-- the program to control what happens in those cases.
397427
398428-- | Always succeeds, but returns the internal GE structure for analysis
399- inspect :: forall m x . MonadGenError m => GenT GE x -> GenT m (GE x )
400- inspect (GenT f) = GenT g
401- where
402- g mode msgs = do geThing <- f mode msgs; pure @ Gen (pure @ m geThing)
429+ inspect :: forall m a . MonadGenError m => GenT GE a -> GenT m (GE a )
430+ inspect (GenT f) = GenT $ \ mode msgs -> liftGenToStrict $ runStrictGen $ f mode msgs
403431
404432-- | Ignore all kinds of Errors, by squashing them into Nothing
405433tryGenT :: MonadGenError m => GenT GE a -> GenT m (Maybe a )
0 commit comments