Skip to content

Commit 3a447f3

Browse files
try to do this quickly
1 parent 3730642 commit 3a447f3

File tree

1 file changed

+61
-33
lines changed

1 file changed

+61
-33
lines changed

src/Constrained/GenT.hs

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ import GHC.Stack
6969
import System.Random
7070
import Test.QuickCheck hiding (Args, Fun)
7171
import 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

114150
instance 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?
119154
instance 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

125159
instance 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.
170204
instance 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
273307
strictGen :: 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
277311
looseGen :: 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
281315
genFromGenT :: GenT GE a -> Gen a
282316
genFromGenT 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.
289319
pureGen :: 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`
293323
listOfT :: MonadGenError m => GenT GE a -> GenT m [a]
294324
listOfT 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`
317347
vectorOfT :: MonadGenError m => Int -> GenT GE a -> GenT m [a]
318348
vectorOfT 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

326356
infixl 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
358388
getMode :: 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
362392
getMessages :: 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
366396
withMode :: 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
390420
sizeT :: 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
405433
tryGenT :: MonadGenError m => GenT GE a -> GenT m (Maybe a)

0 commit comments

Comments
 (0)