2

I have a datatype that looks like this:

data PageLogCommand = LogPage Page
                    | Stop (MVar ())

And I want to create a generator of type Gen PageLogCommand.

For the Stop command though, making a new empty MVar has type IO (MVar a), so how can I get the MVar out of the IO monad and use it to make a Gen type?

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
doctopus
  • 5,349
  • 8
  • 53
  • 105

2 Answers2

2

How about passing the MVar as a parameter to your Gen function? Like

pageLogCommandGen :: MVar () -> Gen PageLogCommand
pageLogCommandGen stopMVar = oneof
  [ LogPage <$> arbitrary
  , pure (Stop stopMVar)
  ]

Then you can generate stopMVar in IO and pass it on like

do stopMVar <- newEmptyMVar
   plc <- generate (pageLogCommandGen stopMVar)
   ...

before you test a property.

sshine
  • 15,635
  • 1
  • 41
  • 66
0

You can't extract a pure value from IO. That's by design.

You can, however, write QuickCheck properties that run in IO; something like this:

myIOProperty :: Testable prop => IO prop
myIOProperty = do
  mvar <- newEmptyMVar
  -- do something with mvar here and return a result

Then use ioProperty or idempotentIOProperty to turn the IO prop value into a Property.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736