<div dir="ltr"><div>Thanks, Li-yao! For anyone else reading this, this is the MonadRandom instance</div><div>I ended up with:</div><div><br></div><div><div>mkGen :: (QCGen -> a) -> Gen a</div><div>mkGen f = MkGen $ \g _ -> f g</div><div><br></div><div>instance MonadRandom Gen where</div><div>    getRandom = mkGen (fst . random)</div><div>    getRandoms = mkGen randoms</div><div>    getRandomR range = mkGen (fst . randomR range)</div><div>    getRandomRs range = mkGen (randomRs range)</div></div><div><br></div><div>With that said, I found that in many cases to get the game states I needed for</div><div>my property tests I had to use more specific generators that took input such as</div><div>a range of number of moves, whether the game was finished or not, the current</div><div>action, etc., so it didn't end up being as useful for me as I hoped.</div><blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><p></p><p></p><p></p><p></p></blockquote><br>On Sunday, August 21, 2016 at 10:37:35 PM UTC+2, Li-yao Xia wrote:<blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Hi Magnus,<p>Import Test.QuickCheck.Gen to get the internals of Gen, which AFAIK is <br>currently the only way to get to the underlying random generator (QCGen).</p><p>getRandom = MkGen $ \g _ -> fst (random g)<br>-- repeat with randomRs, randoms.</p><p>I don't know why Gen is not an instance of MonadRandom either. It seems <br>reasonable to add one, though it might go against some design principle <br>of QuickCheck by ignoring the size parameter.</p><p>Regards,<br>Li-yao</p><p>On 08/21/2016 09:38 PM, Magnus Grindal Bakken wrote:<br>> Is there some easy way to use the Gen type from QuickCheck with the<br>> MonadRandom class?<br>><br>> Links to the packages in question:<br>> <a href="https://hackage.haskell.org/package/MonadRandom" target="_blank" rel="nofollow" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fhackage.haskell.org%2Fpackage%2FMonadRandom\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHyvIViQfrpGYuZCFSXIVDwuZn5Zw';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fhackage.haskell.org%2Fpackage%2FMonadRandom\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHyvIViQfrpGYuZCFSXIVDwuZn5Zw';return true;">https://hackage.haskell.org/<wbr>package/MonadRandom</a><br>> <a href="https://hackage.haskell.org/package/QuickCheck" target="_blank" rel="nofollow" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fhackage.haskell.org%2Fpackage%2FQuickCheck\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEAEpDozS2EcQqVxYMWHkPRT3sJoQ';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fhackage.haskell.org%2Fpackage%2FQuickCheck\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEAEpDozS2EcQqVxYMWHkPRT3sJoQ';return true;">https://hackage.haskell.org/<wbr>package/QuickCheck</a><br>><br>> Some background in case there's an easier way to solve the problem:<br>> I'm toying around with an API for a simple turn-based board game. The<br>> main type in my API is called GameState, and I'm trying to define an<br>> Arbitrary instance for it so I can set up invariants with QuickCheck.<br>> The Arbitrary instance should produce game states that are the result<br>> of playing a random number of random moves.<br>><br>> At certain points in the gameplay the game itself needs to invoke some<br>> randomness. I've designed the public game API to have basically just<br>> two functions:<br>><br>> playAction :: ActionData -> GameState -> GameState<br>> evaluateGameState :: MonadRandom m => GameState -> m GameState<br>><br>> The usage is supposed to be that the client first calls playAction<br>> with an ActionData value that depends on the current move, and<br>> afterwards calls evaluateGameState to evaluate whatever random events<br>> need to happen at that point (e.g. reshuffling a deck of cards). That<br>> way my main "action" logic doesn't need to concern itself with any<br>> form of randomness.<br>><br>> I'm using MonadRandom from Control.Monad.Random because it seems like<br>> a much nicer way to generate random numbers than using RandomGen<br>> directly. However I can't figure out how to make it play nice with<br>> QuickCheck. I can easily set up my Arbitrary instance to call<br>> playAction an arbitrary number of times, but I can't call<br>> evaluateGameState since it lives in the other monad. It would work if<br>> Gen were an instance of MonadRandom, but I can't quite work out how to<br>> write that instance since most functions on Gen only work if the<br>> output type is an instance of Arbitrary, while MonadRandom needs to<br>> work with any types that are part of the Random class. This part<br>> works:<br>><br>> instance MonadRandom Gen where<br>>     getRandomR = choose<br>><br>> But I don't know how to define the other functions on MonadRandom for Gen.<br>><br>> I think I might also be able to use the PropertyM monad transformer:<br>> <a href="https://hackage.haskell.org/package/QuickCheck-2.9.1/docs/Test-QuickCheck-Monadic.html" target="_blank" rel="nofollow" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fhackage.haskell.org%2Fpackage%2FQuickCheck-2.9.1%2Fdocs%2FTest-QuickCheck-Monadic.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHRpLKpW3eYtDscb59kQimPuJ74Jw';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fhackage.haskell.org%2Fpackage%2FQuickCheck-2.9.1%2Fdocs%2FTest-QuickCheck-Monadic.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHRpLKpW3eYtDscb59kQimPuJ74Jw';return true;">https://hackage.haskell.org/<wbr>package/QuickCheck-2.9.1/docs/<wbr>Test-QuickCheck-Monadic.html</a>,<br>> but monad transformers always confuse me so I haven't been able to<br>> figure out how to do that yet either.<br>><br>> I've thought about rewriting the API to use the Gen type instead of<br>> MonadRandom, but it feels kind of iffy to have the API depend on a<br>> testing library.<br>><br>> Has anyone tried to use these libraries together before?<br>> ______________________________<wbr>_________________<br>> Haskell-Cafe mailing list<br>> To (un)subscribe, modify options or view archives go to:<br>> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank" rel="nofollow" onmousedown="this.href='http://www.google.com/url?q\x3dhttp%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fhaskell-cafe\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH7sFgl7KfuDcDlaGGG3ip3kRaoIA';return true;" onclick="this.href='http://www.google.com/url?q\x3dhttp%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fhaskell-cafe\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH7sFgl7KfuDcDlaGGG3ip3kRaoIA';return true;">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>> Only members subscribed via the mailman list are allowed to post.<br>><br>______________________________<wbr>_________________<br>Haskell-Cafe mailing list<br>To (un)subscribe, modify options or view archives go to:<br><a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank" rel="nofollow" onmousedown="this.href='http://www.google.com/url?q\x3dhttp%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fhaskell-cafe\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH7sFgl7KfuDcDlaGGG3ip3kRaoIA';return true;" onclick="this.href='http://www.google.com/url?q\x3dhttp%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fhaskell-cafe\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH7sFgl7KfuDcDlaGGG3ip3kRaoIA';return true;">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>Only members subscribed via the mailman list are allowed to post.</p><p></p><p></p><p></p><p></p></blockquote></div>