quickcheck
quickcheck copied to clipboard
Show instance for ‘Gen _’?
I feel compelled to create this issue, this is as useful as it is not great
instance Show a => Show (Gen a) where
show :: Gen a -> String
show gen = unsafePerformIO (intercalate ", " . map show <$> sample' gen)
Yes this is unsafe, it can go in Test.QuickCheck.Gen.Unsafe
.
This should only be used for debugging, and is very useful to play around with Gen
combinators.
Example 1
We forget if choose
is inclusive or exclusive
>>> choose (0, 4)
4, 4, 4, 4, 0, 2, 1, 1, 2, 3, 2
It generates 0
and 4
so it must generate the closed interval [0..4]
.
Example 2
Easy to experiment..
>>> elements "hello"
'e', 'o', 'l', 'l', 'l', 'o', 'l', 'h', 'h', 'o', 'e'
Example 3
Makes discovery easier
>>> resize 1 (listOf @Int arbitrary)
[], [], [0], [], [-1], [1], [], [0], [], [], [1]
>>> resize 2 (listOf @Int arbitrary)
[], [-2], [1,1], [-2], [0,0], [], [], [0,2], [-1,2], [], [-2,2]
>>> resize 3 (listOf @Int arbitrary)
[-2,-1,1], [-3], [], [3,-2], [-2,0,-1], [-3], [2], [-3], [-2,3,1], [], [3,3,2]
>>> resize 4 (listOf @Int arbitrary)
[-3,0,-2], [], [4,1,-2], [2,-2,1,-2], [3], [0,4,0], [-3,-4,0,2], [1,3], [1], [0,0,4,-3], [2,-4,-4]
>>> resize 5 (listOf @Int arbitrary)
[-5], [0,-2,1], [], [5,-2,2,0], [-4,-4,5,0], [-5,5,3,-4,0], [-1], [-1,2,4], [-5,2,-4], [4,2,0,-2], [2,0]
Example 4
Random
>>> arbitrary
(), (), (), (), (), (), (), (), (), (), ()
>>> arbitrary @Int
0, -1, 4, -5, -7, -4, -10, -12, 14, -15, 0
>>> arbitrary @String
"", ",\SUB", "", "@\210\241", "\244\&9", "", "*:\158\aYpV#si", "$Dp{/", "P\164/e'\228h\vR|\SOHO_9\ETX\EM", ":/\151\229", "dI\tC\231\DC4\134V\226\a\r\DLE"
>>> arbitrary @String `suchThat` all isAlpha
"", "", "", "C", "tt", "", "M", "", "", "c", "s"
>>> index xs = choose (0, length xs - 1)
>>> xs = [False,True,False]
>>> xs' = [False,True,False,True,False,False,False,True]
>>> index xs
2, 2, 0, 0, 1, 2, 1, 0, 1, 1, 2
>>> index xs `suchThat` even
2, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0
>>> index xs `suchThat` (xs !!)
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
>>> index xs
2, 3, 1, 0, 5, 4, 7, 4, 5, 4, 6
>>> index xs `suchThat` even
6, 4, 4, 6, 6, 6, 2, 6, 6, 2, 0
>>> index xs `suchThat` (xs !!)
3, 1, 7, 7, 1, 3, 7, 3, 3, 1, 3
Misc
>>> show (arbitrary @Int) == show (arbitrary @Int)
False
instance Arbitrary a => Arbitrary (Gen a) where
arbitrary :: Gen (Gen a)
arbitrary = pure @Gen (arbitrary @a)
prop_showGen :: Gen Int -> Property
prop_showGen gen = counterexample ("\nshow₁: " ++ show₁ ++ "\nshow₂: " ++ show₂) (show₁ == show₂)
where
(show₁, show₂) = (show gen, show gen)
>>> quickCheck prop_showGen
*** Failed! Falsifiable (after 1 test):
0, -1, -4, 2, -7, 4, -5, 14, 3, -12, -19
show₁: 0, 2, -1, 5, -7, -8, -12, -3, 12, -13, 19
show₂: 0, 2, 0, 5, 1, -4, -2, -8, 14, -4, 14
I'm :-1:. As sample (arbitrary @Int)
isn't that much longer. Hiding non-deterministic IO is imho one of the worst things you can do.
That's what I expected. It has been useful to me so I will continue using it in personal configuration but it is obviously iffy.
You correctly point to writing sample
explicitly, in practice it limited my experience. I don't know about others. Similar to the convenience of
>>> 10 + 2
12
>>> getCurrentTime
2017 - 1 - 7 20 : 12 : 3.081522289 UTC
rather than
>>> print (10 + 2)
12
>>> getCurrentTime
<interactive>:12:1: error:
• No instance for (Show (IO UTCTime)) arising from a use of ‘print’
• In a stmt of an interactive GHCi command: print it
>>> time <- getCurrentTime
>>> print time
2017 - 1 - 7 20 : 12 : 3.081522289 UTC
As usual I don't care so much about the final decision :) thanks for humouring me
I'm going to close this as wontfix on account of being boring and conservative about introducing unsafePerformIO
in combation with randomness.