-
Notifications
You must be signed in to change notification settings - Fork 130
Expand file tree
/
Copy pathArbitrary.hs
More file actions
1979 lines (1626 loc) · 64.2 KB
/
Copy pathArbitrary.hs
File metadata and controls
1979 lines (1626 loc) · 64.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-- | Type classes for random generation of values.
--
-- __Note__: the contents of this module are re-exported by
-- "Test.QuickCheck". You do not need to import it directly.
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
#ifndef NO_GENERICS
{-# LANGUAGE DefaultSignatures, FlexibleContexts, TypeOperators #-}
{-# LANGUAGE FlexibleInstances, KindSignatures, ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
#if __GLASGOW_HASKELL__ >= 710
#define OVERLAPPING_ {-# OVERLAPPING #-}
#else
{-# LANGUAGE OverlappingInstances #-}
#define OVERLAPPING_
#endif
#endif
#ifndef NO_POLYKINDS
{-# LANGUAGE PolyKinds #-}
#endif
#ifndef NO_SAFE_HASKELL
{-# LANGUAGE Trustworthy #-}
#endif
#ifndef NO_NEWTYPE_DERIVING
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
#endif
module Test.QuickCheck.Arbitrary
(
-- * Arbitrary and CoArbitrary classes
Arbitrary(..)
, CoArbitrary(..)
-- ** Unary and Binary classes
, Arbitrary1(..)
, arbitrary1
, shrink1
, Arbitrary2(..)
, arbitrary2
, shrink2
-- ** Helper functions for implementing arbitrary
, applyArbitrary2
, applyArbitrary3
, applyArbitrary4
, arbitrarySizedIntegral -- :: Integral a => Gen a
, arbitrarySizedNatural -- :: Integral a => Gen a
, arbitraryBoundedIntegral -- :: (Bounded a, Integral a) => Gen a
, arbitrarySizedBoundedIntegral -- :: (Bounded a, Integral a) => Gen a
, arbitrarySizedFractional -- :: Fractional a => Gen a
, arbitraryBoundedRandom -- :: (Bounded a, Random a) => Gen a
, arbitraryBoundedEnum -- :: (Bounded a, Enum a) => Gen a
-- ** Generators for various kinds of character
, arbitraryUnicodeChar -- :: Gen Char
, arbitraryASCIIChar -- :: Gen Char
, arbitraryPrintableChar -- :: Gen Char
-- ** Helper functions for implementing shrink
#ifndef NO_GENERICS
, RecursivelyShrink
, GSubterms
, genericShrink -- :: (Generic a, Arbitrary a, RecursivelyShrink (Rep a), GSubterms (Rep a) a) => a -> [a]
, subterms -- :: (Generic a, Arbitrary a, GSubterms (Rep a) a) => a -> [a]
, recursivelyShrink -- :: (Generic a, RecursivelyShrink (Rep a)) => a -> [a]
, genericCoarbitrary -- :: (Generic a, GCoArbitrary (Rep a)) => a -> Gen b -> Gen b
#endif
, shrinkNothing -- :: a -> [a]
, shrinkList -- :: (a -> [a]) -> [a] -> [[a]]
, shrinkMap -- :: Arbitrary a -> (a -> b) -> (b -> a) -> b -> [b]
, shrinkMapBy -- :: (a -> b) -> (b -> a) -> (a -> [a]) -> b -> [b]
, shrinkIntegral -- :: Integral a => a -> [a]
, shrinkRealFrac -- :: RealFrac a => a -> [a]
, shrinkBoundedEnum -- :: (Bounded a, Enum a) => a -> [a]
, shrinkDecimal -- :: RealFrac a => a -> [a]
-- ** Helper functions for implementing coarbitrary
, coarbitraryIntegral -- :: Integral a => a -> Gen b -> Gen b
, coarbitraryReal -- :: Real a => a -> Gen b -> Gen b
, coarbitraryShow -- :: Show a => a -> Gen b -> Gen b
, coarbitraryEnum -- :: Enum a => a -> Gen b -> Gen b
, (><)
-- ** Generators which use arbitrary
, vector -- :: Arbitrary a => Int -> Gen [a]
, orderedList -- :: (Ord a, Arbitrary a) => Gen [a]
, infiniteList -- :: Arbitrary a => Gen [a]
)
where
--------------------------------------------------------------------------
-- imports
import Control.Applicative
import Data.Foldable(toList)
#if MIN_VERSION_random(1,3,0)
import System.Random(Random, uniformByteArray)
#else
import System.Random(Random)
#endif
import Test.QuickCheck.Gen
import Test.QuickCheck.Random
import Test.QuickCheck.Gen.Unsafe
#if defined(__MHS__)
-- These two are not exported by Control.Applicative.
-- Why should they be? They are just bloat.
import Data.ZipList
import Control.WrappedMonad
#endif
import Data.Char
( ord
, isLower
, isUpper
, toLower
, isDigit
, isSpace
, isPrint
, generalCategory
, GeneralCategory(..)
)
#ifndef NO_FIXED
import Data.Fixed
( Fixed
, HasResolution
)
#endif
import Data.Ratio
( Ratio
, (%)
, numerator
, denominator
)
import Data.Complex
( Complex((:+)) )
import Data.List
( sort
, nub
)
import Data.Version (Version (..))
#if defined(MIN_VERSION_base)
import Numeric.Natural
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
import System.IO
( Newline(..)
, NewlineMode(..)
, SeekMode(..)
, BufferMode(..)
, TextEncoding
, latin1, utf8, utf8_bom, utf16, utf16le, utf16be, utf32, utf32le, utf32be, localeEncoding, char8
, IOMode(..)
)
#endif
import Control.Monad
( liftM
, liftM2
, liftM3
, liftM4
, liftM5
)
import Data.Int(Int8, Int16, Int32, Int64)
import Data.Word(Word, Word8, Word16, Word32, Word64)
import System.Exit (ExitCode(..))
import Foreign.C.Types
#ifndef NO_GENERICS
import GHC.Generics
#endif
import qualified Data.Set as Set
import qualified Data.IntSet as IntSet
#if MIN_VERSION_containers(0,5,0)
import qualified Data.Map.Strict as Map
import qualified Data.IntMap.Strict as IntMap
#else
import qualified Data.Map as Map
import qualified Data.IntMap as IntMap
#endif
import qualified Data.Sequence as Sequence
import qualified Data.Tree as Tree
import qualified Data.Monoid as Monoid
#if defined(MIN_VERSION_base)
import qualified Data.Semigroup as Semigroup
#endif
#ifndef NO_TRANSFORMERS
import Data.Functor.Identity
import Data.Functor.Constant
import Data.Functor.Compose
import Data.Functor.Product
#endif
#if defined(MIN_VERSION_base)
import qualified Data.Semigroup as Semigroup
import Data.Ord
import System.Console.GetOpt
( ArgDescr(..), ArgOrder(..), OptDescr(..) )
import Data.Functor.Contravariant
import Data.Array.Byte
import qualified GHC.Exts as Exts
#if MIN_VERSION_base(4,16,0)
import Data.Tuple
#else
import Data.Tuple.Solo
#endif
#endif
import Data.Bits
import Text.Printf
import Test.QuickCheck.Compat
--------------------------------------------------------------------------
-- ** class Arbitrary
-- | Random generation and shrinking of values.
--
-- QuickCheck provides @Arbitrary@ instances for most types in @base@,
-- except those which incur extra dependencies.
-- For a wider range of @Arbitrary@ instances see the
-- <http://hackage.haskell.org/package/quickcheck-instances quickcheck-instances>
-- package.
class Arbitrary a where
-- | A generator for values of the given type.
--
-- It is worth spending time thinking about what sort of test data
-- you want - good generators are often the difference between
-- finding bugs and not finding them. You can use 'sample',
-- 'Test.QuickCheck.label' and 'Test.QuickCheck.classify' to check the quality
-- of your test data.
--
-- There is no generic @arbitrary@ implementation included because we don't
-- know how to make a high-quality one. If you want one, consider using the
-- <http://hackage.haskell.org/package/testing-feat testing-feat> or
-- <http://hackage.haskell.org/package/generic-random generic-random> packages.
--
-- The <http://www.cse.chalmers.se/~rjmh/QuickCheck/manual.html QuickCheck manual>
-- goes into detail on how to write good generators. Make sure to look at it,
-- especially if your type is recursive!
arbitrary :: Gen a
-- | Produces a (possibly) empty list of all the possible
-- immediate shrinks of the given value.
--
-- The default implementation returns the empty list, so will not try to
-- shrink the value. If your data type has no special invariants, you can
-- enable shrinking by defining @shrink = 'genericShrink'@, but by customising
-- the behaviour of @shrink@ you can often get simpler counterexamples.
--
-- Most implementations of 'shrink' should try at least three things:
--
-- 1. Shrink a term to any of its immediate subterms.
-- You can use 'subterms' to do this.
--
-- 2. Recursively apply 'shrink' to all immediate subterms.
-- You can use 'recursivelyShrink' to do this.
--
-- 3. Type-specific shrinkings such as replacing a constructor by a
-- simpler constructor.
--
-- For example, suppose we have the following implementation of binary trees:
--
-- > data Tree a = Nil | Branch a (Tree a) (Tree a)
--
-- We can then define 'shrink' as follows:
--
-- > shrink Nil = []
-- > shrink (Branch x l r) =
-- > -- shrink Branch to Nil
-- > [Nil] ++
-- > -- shrink to non-Nil subterms
-- > [t | t@Branch{} <- [l, r]] ++
-- > -- recursively shrink subterms
-- > [Branch x' l' r' | (x', l', r') <- shrink (x, l, r)]
--
-- There are a couple of subtleties here:
--
-- * QuickCheck tries the shrinking candidates in the order they
-- appear in the list, so we put more aggressive shrinking steps
-- (such as replacing the whole tree by @Nil@) before smaller
-- ones (such as recursively shrinking the subtrees).
--
-- * It is tempting to write the last line as
-- @[Branch x' l' r' | x' <- shrink x, l' <- shrink l, r' <- shrink r]@
-- but this is the /wrong thing/! It will force QuickCheck to shrink
-- @x@, @l@ and @r@ in tandem, and shrinking will stop once /one/ of
-- the three is fully shrunk.
--
-- There is a fair bit of boilerplate in the code above.
-- We can avoid it with the help of some generic functions.
-- The function 'genericShrink' tries shrinking a term to all of its
-- subterms and, failing that, recursively shrinks the subterms.
-- Using it, we can define 'shrink' as:
--
-- > shrink x = shrinkToNil x ++ genericShrink x
-- > where
-- > shrinkToNil Nil = []
-- > shrinkToNil (Branch _ l r) = [Nil]
--
-- 'genericShrink' is a combination of 'subterms', which shrinks
-- a term to any of its subterms, and 'recursivelyShrink', which shrinks
-- all subterms of a term. These may be useful if you need a bit more
-- control over shrinking than 'genericShrink' gives you.
--
-- A final gotcha: we cannot define 'shrink' as simply @'shrink' x = Nil:'genericShrink' x@
-- as this shrinks @Nil@ to @Nil@, and shrinking will go into an
-- infinite loop.
--
-- If all this leaves you bewildered, you might try @'shrink' = 'genericShrink'@ to begin with,
-- after deriving @Generic@ for your type. However, if your data type has any
-- special invariants, you will need to check that 'genericShrink' can't break those invariants.
shrink :: a -> [a]
shrink _ = []
-- | Lifting of the 'Arbitrary' class to unary type constructors.
class Arbitrary1 f where
liftArbitrary :: Gen a -> Gen (f a)
liftShrink :: (a -> [a]) -> f a -> [f a]
liftShrink _ _ = []
arbitrary1 :: (Arbitrary1 f, Arbitrary a) => Gen (f a)
arbitrary1 = liftArbitrary arbitrary
shrink1 :: (Arbitrary1 f, Arbitrary a) => f a -> [f a]
shrink1 = liftShrink shrink
-- | Lifting of the 'Arbitrary' class to binary type constructors.
class Arbitrary2 f where
liftArbitrary2 :: Gen a -> Gen b -> Gen (f a b)
liftShrink2 :: (a -> [a]) -> (b -> [b]) -> f a b -> [f a b]
liftShrink2 _ _ _ = []
arbitrary2 :: (Arbitrary2 f, Arbitrary a, Arbitrary b) => Gen (f a b)
arbitrary2 = liftArbitrary2 arbitrary arbitrary
shrink2 :: (Arbitrary2 f, Arbitrary a, Arbitrary b) => f a b -> [f a b]
shrink2 = liftShrink2 shrink shrink
#ifndef NO_GENERICS
-- | Shrink a term to any of its immediate subterms,
-- and also recursively shrink all subterms.
genericShrink :: (Generic a, RecursivelyShrink (Rep a), GSubterms (Rep a) a) => a -> [a]
genericShrink x = subterms x ++ recursivelyShrink x
-- | Recursively shrink all immediate subterms.
recursivelyShrink :: (Generic a, RecursivelyShrink (Rep a)) => a -> [a]
recursivelyShrink = map to . grecursivelyShrink . from
class RecursivelyShrink f where
grecursivelyShrink :: f a -> [f a]
instance (RecursivelyShrink f, RecursivelyShrink g) => RecursivelyShrink (f :*: g) where
grecursivelyShrink (x :*: y) =
[x' :*: y | x' <- grecursivelyShrink x] ++
[x :*: y' | y' <- grecursivelyShrink y]
instance (RecursivelyShrink f, RecursivelyShrink g) => RecursivelyShrink (f :+: g) where
grecursivelyShrink (L1 x) = map L1 (grecursivelyShrink x)
grecursivelyShrink (R1 x) = map R1 (grecursivelyShrink x)
instance RecursivelyShrink f => RecursivelyShrink (M1 i c f) where
grecursivelyShrink (M1 x) = map M1 (grecursivelyShrink x)
instance Arbitrary a => RecursivelyShrink (K1 i a) where
grecursivelyShrink (K1 x) = map K1 (shrink x)
instance RecursivelyShrink U1 where
grecursivelyShrink U1 = []
instance RecursivelyShrink V1 where
-- The empty type can't be shrunk to anything.
grecursivelyShrink _ = []
-- | All immediate subterms of a term.
subterms :: (Generic a, GSubterms (Rep a) a) => a -> [a]
subterms = gSubterms . from
class GSubterms f a where
-- | Provides the immediate subterms of a term that are of the same type
-- as the term itself.
--
-- Requires a constructor to be stripped off; this means it skips through
-- @M1@ wrappers and returns @[]@ on everything that's not `(:*:)` or `(:+:)`.
--
-- Once a `(:*:)` or `(:+:)` constructor has been reached, this function
-- delegates to `gSubtermsIncl` to return the immediately next constructor
-- available.
gSubterms :: f a -> [a]
instance GSubterms V1 a where
-- The empty type can't be shrunk to anything.
gSubterms _ = []
instance GSubterms U1 a where
gSubterms U1 = []
instance (GSubtermsIncl f a, GSubtermsIncl g a) => GSubterms (f :*: g) a where
gSubterms (l :*: r) = gSubtermsIncl l ++ gSubtermsIncl r
instance (GSubtermsIncl f a, GSubtermsIncl g a) => GSubterms (f :+: g) a where
gSubterms (L1 x) = gSubtermsIncl x
gSubterms (R1 x) = gSubtermsIncl x
instance GSubterms f a => GSubterms (M1 i c f) a where
gSubterms (M1 x) = gSubterms x
instance GSubterms (K1 i a) b where
gSubterms (K1 _) = []
class GSubtermsIncl f a where
-- | Provides the immediate subterms of a term that are of the same type
-- as the term itself.
--
-- In contrast to `gSubterms`, this returns the immediate next constructor
-- available.
gSubtermsIncl :: f a -> [a]
instance GSubtermsIncl V1 a where
-- The empty type can't be shrunk to anything.
gSubtermsIncl _ = []
instance GSubtermsIncl U1 a where
gSubtermsIncl U1 = []
instance (GSubtermsIncl f a, GSubtermsIncl g a) => GSubtermsIncl (f :*: g) a where
gSubtermsIncl (l :*: r) = gSubtermsIncl l ++ gSubtermsIncl r
instance (GSubtermsIncl f a, GSubtermsIncl g a) => GSubtermsIncl (f :+: g) a where
gSubtermsIncl (L1 x) = gSubtermsIncl x
gSubtermsIncl (R1 x) = gSubtermsIncl x
instance GSubtermsIncl f a => GSubtermsIncl (M1 i c f) a where
gSubtermsIncl (M1 x) = gSubtermsIncl x
-- This is the important case: We've found a term of the same type.
instance OVERLAPPING_ GSubtermsIncl (K1 i a) a where
gSubtermsIncl (K1 x) = [x]
instance GSubtermsIncl (K1 i a) b where
gSubtermsIncl (K1 _) = []
#endif
-- instances
instance (CoArbitrary a) => Arbitrary1 ((->) a) where
liftArbitrary arbB = promote (`coarbitrary` arbB)
instance (CoArbitrary a, Arbitrary b) => Arbitrary (a -> b) where
arbitrary = arbitrary1
instance Arbitrary () where
arbitrary = return ()
instance Arbitrary Bool where
arbitrary = chooseEnum (False,True)
shrink True = [False]
shrink False = []
instance Arbitrary Ordering where
arbitrary = elements [LT, EQ, GT]
shrink GT = [EQ, LT]
shrink LT = [EQ]
shrink EQ = []
instance Arbitrary1 Maybe where
liftArbitrary arb = frequency [(1, return Nothing), (3, liftM Just arb)]
liftShrink shr (Just x) = Nothing : [ Just x' | x' <- shr x ]
liftShrink _ Nothing = []
instance Arbitrary a => Arbitrary (Maybe a) where
arbitrary = arbitrary1
shrink = shrink1
instance Arbitrary2 Either where
liftArbitrary2 arbA arbB = oneof [liftM Left arbA, liftM Right arbB]
liftShrink2 shrA _ (Left x) = [ Left x' | x' <- shrA x ]
liftShrink2 _ shrB (Right y) = [ Right y' | y' <- shrB y ]
instance Arbitrary a => Arbitrary1 (Either a) where
liftArbitrary = liftArbitrary2 arbitrary
liftShrink = liftShrink2 shrink
instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b) where
arbitrary = arbitrary2
shrink = shrink2
instance Arbitrary1 [] where
liftArbitrary = listOf
liftShrink = shrinkList
instance Arbitrary a => Arbitrary [a] where
arbitrary = arbitrary1
shrink = shrink1
-- | Shrink a list of values given a shrinking function for individual values.
shrinkList :: (a -> [a]) -> [a] -> [[a]]
shrinkList shr xs = concat [ removes k n xs | k <- takeWhile (>0) (iterate (`div`2) n) ]
++ shrinkOne xs
where
n = length xs
shrinkOne [] = []
shrinkOne (x:xs) = [ x':xs | x' <- shr x ]
++ [ x:xs' | xs' <- shrinkOne xs ]
removes k n xs
| k > n = []
| null xs2 = [[]]
| otherwise = xs2 : map (xs1 ++) (removes k (n-k) xs2)
where
xs1 = take k xs
xs2 = drop k xs
#if defined(MIN_VERSION_base)
instance Arbitrary1 NonEmpty where
liftArbitrary arb = NonEmpty.fromList <$> listOf1 arb
liftShrink shr xs = [ NonEmpty.fromList xs' | xs' <- liftShrink shr (NonEmpty.toList xs), not (null xs') ]
instance Arbitrary a => Arbitrary (NonEmpty a) where
arbitrary = arbitrary1
shrink = shrink1
#endif
instance Integral a => Arbitrary (Ratio a) where
arbitrary = sized $ \ n -> do
denom <- chooseInt (1, max 1 n)
let lb | isNonNegativeType fromI = 0
| otherwise = (-n*denom)
-- NOTE: this is a trick to make sure we get around lack of scoped type
-- variables by pinning the result-type of fromIntegral.
fromI = fromIntegral
numer <- chooseInt (lb, n*denom)
pure $ fromI numer % fromI denom
shrink = shrinkRealFrac
#if defined(MIN_VERSION_base)
instance Arbitrary a => Arbitrary (Complex a) where
#else
instance (RealFloat a, Arbitrary a) => Arbitrary (Complex a) where
#endif
arbitrary = liftM2 (:+) arbitrary arbitrary
shrink (x :+ y) = [ x' :+ y | x' <- shrink x ] ++
[ x :+ y' | y' <- shrink y ]
#ifndef NO_FIXED
instance HasResolution a => Arbitrary (Fixed a) where
arbitrary = arbitrarySizedFractional
shrink = shrinkDecimal
#endif
instance Arbitrary2 (,) where
liftArbitrary2 = liftM2 (,)
liftShrink2 shrA shrB (x, y) =
[ (x', y) | x' <- shrA x ]
++ [ (x, y') | y' <- shrB y ]
instance (Arbitrary a) => Arbitrary1 ((,) a) where
liftArbitrary = liftArbitrary2 arbitrary
liftShrink = liftShrink2 shrink
instance (Arbitrary a, Arbitrary b) => Arbitrary (a,b) where
arbitrary = arbitrary2
shrink = shrink2
instance (Arbitrary a, Arbitrary b, Arbitrary c)
=> Arbitrary (a,b,c)
where
arbitrary = liftM3 (,,) arbitrary arbitrary arbitrary
shrink (x, y, z) =
[ (x', y', z')
| (x', (y', z')) <- shrink (x, (y, z)) ]
instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d)
=> Arbitrary (a,b,c,d)
where
arbitrary = liftM4 (,,,) arbitrary arbitrary arbitrary arbitrary
shrink (w, x, y, z) =
[ (w', x', y', z')
| (w', (x', (y', z'))) <- shrink (w, (x, (y, z))) ]
instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e)
=> Arbitrary (a,b,c,d,e)
where
arbitrary = liftM5 (,,,,) arbitrary arbitrary arbitrary arbitrary arbitrary
shrink (v, w, x, y, z) =
[ (v', w', x', y', z')
| (v', (w', (x', (y', z')))) <- shrink (v, (w, (x, (y, z)))) ]
instance ( Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e
, Arbitrary f
)
=> Arbitrary (a,b,c,d,e,f)
where
arbitrary = return (,,,,,)
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary <*> arbitrary
shrink (u, v, w, x, y, z) =
[ (u', v', w', x', y', z')
| (u', (v', (w', (x', (y', z'))))) <- shrink (u, (v, (w, (x, (y, z))))) ]
instance ( Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e
, Arbitrary f, Arbitrary g
)
=> Arbitrary (a,b,c,d,e,f,g)
where
arbitrary = return (,,,,,,)
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary <*> arbitrary <*> arbitrary
shrink (t, u, v, w, x, y, z) =
[ (t', u', v', w', x', y', z')
| (t', (u', (v', (w', (x', (y', z')))))) <- shrink (t, (u, (v, (w, (x, (y, z)))))) ]
instance ( Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e
, Arbitrary f, Arbitrary g, Arbitrary h
)
=> Arbitrary (a,b,c,d,e,f,g,h)
where
arbitrary = return (,,,,,,,)
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
shrink (s, t, u, v, w, x, y, z) =
[ (s', t', u', v', w', x', y', z')
| (s', (t', (u', (v', (w', (x', (y', z')))))))
<- shrink (s, (t, (u, (v, (w, (x, (y, z))))))) ]
instance ( Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e
, Arbitrary f, Arbitrary g, Arbitrary h, Arbitrary i
)
=> Arbitrary (a,b,c,d,e,f,g,h,i)
where
arbitrary = return (,,,,,,,,)
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary
shrink (r, s, t, u, v, w, x, y, z) =
[ (r', s', t', u', v', w', x', y', z')
| (r', (s', (t', (u', (v', (w', (x', (y', z'))))))))
<- shrink (r, (s, (t, (u, (v, (w, (x, (y, z)))))))) ]
instance ( Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e
, Arbitrary f, Arbitrary g, Arbitrary h, Arbitrary i, Arbitrary j
)
=> Arbitrary (a,b,c,d,e,f,g,h,i,j)
where
arbitrary = return (,,,,,,,,,)
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
<*> arbitrary <*> arbitrary
shrink (q, r, s, t, u, v, w, x, y, z) =
[ (q', r', s', t', u', v', w', x', y', z')
| (q', (r', (s', (t', (u', (v', (w', (x', (y', z')))))))))
<- shrink (q, (r, (s, (t, (u, (v, (w, (x, (y, z))))))))) ]
-- typical instance for primitive (numerical) types
instance Arbitrary Integer where
arbitrary = arbitrarySizedIntegral
shrink = shrinkIntegral
#if defined(MIN_VERSION_base)
instance Arbitrary Natural where
arbitrary = arbitrarySizedNatural
shrink = shrinkIntegral
#endif
instance Arbitrary Int where
arbitrary = arbitrarySizedIntegral
shrink = shrinkIntegral
instance Arbitrary Int8 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Int16 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Int32 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Int64 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Word where
arbitrary = arbitrarySizedNatural
shrink = shrinkIntegral
instance Arbitrary Word8 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Word16 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Word32 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Word64 where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary Char where
arbitrary =
frequency
[(3, arbitraryASCIIChar),
(1, arbitraryUnicodeChar)]
shrink c = filter (<. c) $ nub
$ ['a','b','c']
++ [ toLower c | isUpper c ]
++ ['A','B','C']
++ ['1','2','3']
++ [' ','\n']
where
a <. b = stamp a < stamp b
stamp a = ( (not (isLower a)
, not (isUpper a)
, not (isDigit a))
, (not (a==' ')
, not (isSpace a)
, a)
)
instance Arbitrary Float where
arbitrary = oneof
-- generate 0..1 numbers with full precision
[ genFloat
-- generate integral numbers
, fromIntegral <$> (arbitrary :: Gen Int)
-- generate fractions with small denominators
, smallDenominators
-- uniform -size..size with with denominators ~ size
, uniform
-- and uniform -size..size with higher precision
, arbitrarySizedFractional
]
where
smallDenominators = sized $ \n -> do
i <- chooseInt (0, min n 256)
pure (fromRational (streamNth i rationalUniverse))
uniform = sized $ \n -> do
let n' = toInteger n
b <- chooseInteger (1, max 1 n')
a <- chooseInteger ((-n') * b, n' * b)
return (fromRational (a % b))
shrink = shrinkDecimal
instance Arbitrary Double where
arbitrary = oneof
-- generate 0..1 numbers with full precision
[ genDouble
-- generate integral numbers
, fromIntegral <$> (arbitrary :: Gen Int)
-- generate fractions with small denominators
, smallDenominators
-- uniform -size..size with with denominators ~ size
, uniform
-- and uniform -size..size with higher precision
, arbitrarySizedFractional
]
where
smallDenominators = sized $ \n -> do
i <- chooseInt (0, min n 256)
pure (fromRational (streamNth i rationalUniverse))
uniform = sized $ \n -> do
let n' = toInteger n
b <- chooseInteger (1, max 1 n')
a <- chooseInteger ((-n') * b, n' * b)
return (fromRational (a % b))
shrink = shrinkDecimal
instance Arbitrary CChar where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CSChar where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CUChar where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CShort where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CUShort where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CInt where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CUInt where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CLong where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CULong where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CPtrdiff where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CSize where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CWchar where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CSigAtomic where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CLLong where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CULLong where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CIntPtr where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CUIntPtr where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CIntMax where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
instance Arbitrary CUIntMax where
arbitrary = arbitrarySizedBoundedIntegral
shrink = shrinkIntegral
#ifndef NO_CTYPES_CONSTRUCTORS
-- The following four types have no Bounded instance,
-- so we fake it by discovering the bounds at runtime.
instance Arbitrary CClock where
arbitrary = fmap CClock arbitrary
shrink (CClock x) = map CClock (shrink x)
instance Arbitrary CTime where
arbitrary = fmap CTime arbitrary
shrink (CTime x) = map CTime (shrink x)
#ifndef NO_FOREIGN_C_USECONDS
instance Arbitrary CUSeconds where
arbitrary = fmap CUSeconds arbitrary
shrink (CUSeconds x) = map CUSeconds (shrink x)
instance Arbitrary CSUSeconds where
arbitrary = fmap CSUSeconds arbitrary
shrink (CSUSeconds x) = map CSUSeconds (shrink x)
#endif
#endif
instance Arbitrary CFloat where
arbitrary = arbitrarySizedFractional
shrink = shrinkDecimal
instance Arbitrary CDouble where
arbitrary = arbitrarySizedFractional
shrink = shrinkDecimal
-- Arbitrary instances for container types
-- | WARNING: Users working on the internals of the @Set@ type via e.g. @Data.Set.Internal@
-- should be aware that this instance aims to give a good representation of @Set a@
-- as mathematical sets but *does not* aim to provide a varied distribution over the
-- underlying representation.
instance (Ord a, Arbitrary a) => Arbitrary (Set.Set a) where
arbitrary = fmap Set.fromList arbitrary
shrink = map Set.fromList . shrink . Set.toList
instance (Ord k, Arbitrary k) => Arbitrary1 (Map.Map k) where
liftArbitrary = fmap Map.fromList . liftArbitrary . liftArbitrary
liftShrink shr = map Map.fromList . liftShrink (liftShrink shr) . Map.toList
-- | WARNING: The same warning as for @Arbitrary (Set a)@ applies here.
instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map.Map k v) where
arbitrary = arbitrary1
shrink = shrink1
-- | WARNING: The same warning as for @Arbitrary (Set a)@ applies here.
instance Arbitrary IntSet.IntSet where
arbitrary = fmap IntSet.fromList arbitrary
shrink = map IntSet.fromList . shrink . IntSet.toList
-- | WARNING: The same warning as for @Arbitrary (Set a)@ applies here.
instance Arbitrary1 IntMap.IntMap where
liftArbitrary = fmap IntMap.fromList . liftArbitrary . liftArbitrary
liftShrink shr = map IntMap.fromList . liftShrink (liftShrink shr) . IntMap.toList
-- | WARNING: The same warning as for @Arbitrary (Set a)@ applies here.
instance Arbitrary a => Arbitrary (IntMap.IntMap a) where
arbitrary = arbitrary1
shrink = shrink1
instance Arbitrary1 Sequence.Seq where
liftArbitrary = fmap Sequence.fromList . liftArbitrary
liftShrink shr = map Sequence.fromList . liftShrink shr . toList
-- | WARNING: The same warning as for @Arbitrary (Set a)@ applies here.
instance Arbitrary a => Arbitrary (Sequence.Seq a) where
arbitrary = arbitrary1
shrink = shrink1
instance Arbitrary1 Tree.Tree where
liftArbitrary arb = sized $ \n -> do
k <- chooseInt (0, n)
go k
where
go n = do -- n is the size of the trees.
value <- arb
pars <- arbPartition (n - 1) -- can go negative!
forest <- mapM go pars
return $ Tree.Node value forest
arbPartition :: Int -> Gen [Int]
arbPartition k = case compare k 1 of
LT -> pure []
EQ -> pure [1]
GT -> do
first <- chooseInt (1, k)
rest <- arbPartition $ k - first
shuffle (first : rest)
liftShrink shr = go
where
go (Tree.Node val forest) = forest ++
[ Tree.Node e fs
| (e, fs) <- liftShrink2 shr (liftShrink go) (val, forest)
]
instance Arbitrary a => Arbitrary (Tree.Tree a) where
arbitrary = arbitrary1
shrink = shrink1
-- Arbitrary instance for Ziplist
instance Arbitrary1 ZipList where
liftArbitrary = fmap ZipList . liftArbitrary
liftShrink shr = map ZipList . liftShrink shr . getZipList
instance Arbitrary a => Arbitrary (ZipList a) where
arbitrary = arbitrary1
shrink = shrink1
#ifndef NO_TRANSFORMERS
-- Arbitrary instance for transformers' Functors
instance Arbitrary1 Identity where
liftArbitrary = fmap Identity
liftShrink shr = map Identity . shr . runIdentity
instance Arbitrary a => Arbitrary (Identity a) where
arbitrary = arbitrary1
shrink = shrink1
instance Arbitrary2 Constant where
liftArbitrary2 arbA _ = fmap Constant arbA
liftShrink2 shrA _ = fmap Constant . shrA . getConstant
instance Arbitrary a => Arbitrary1 (Constant a) where
liftArbitrary = liftArbitrary2 arbitrary
liftShrink = liftShrink2 shrink