packages feed

generic-random 0.5.0.0 → 1.0.0.0

raw patch · 11 files changed

+743/−416 lines, 11 filesdep +generic-randomdep −boltzmann-samplersdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: generic-random

Dependencies removed: boltzmann-samplers

Dependency ranges changed: base

API changes (from Hackage documentation)

- Generic.Random.Generic: (%) :: WeightBuilder a => W (First a) -> Prec a r -> (a, Int, r)
- Generic.Random.Generic: S :: n -> S n
- Generic.Random.Generic: Z :: Z
- Generic.Random.Generic: class BaseCases n f
- Generic.Random.Generic: class ListBaseCases n f
- Generic.Random.Generic: data S n
- Generic.Random.Generic: data W (c :: Symbol)
- Generic.Random.Generic: data Weights a
- Generic.Random.Generic: data Z
- Generic.Random.Generic: genericArbitrary :: forall a. (Generic a, GA Unsized (Rep a)) => Weights a -> Gen a
- Generic.Random.Generic: genericArbitrary' :: forall n a. (Generic a, GA (Sized n) (Rep a)) => n -> Weights a -> Gen a
- Generic.Random.Generic: genericArbitraryU :: forall a. (Generic a, GA Unsized (Rep a), UniformWeight (Weights_ (Rep a))) => Gen a
- Generic.Random.Generic: genericArbitraryU0 :: forall n a. (Generic a, GA (Sized Z) (Rep a), UniformWeight (Weights_ (Rep a))) => Gen a
- Generic.Random.Generic: genericArbitraryU1 :: forall n a. (Generic a, GA (Sized (S Z)) (Rep a), UniformWeight (Weights_ (Rep a))) => Gen a
- Generic.Random.Generic: type BaseCases' n a = (Generic a, ListBaseCases n (Rep a))
- Generic.Random.Generic: uniform :: UniformWeight (Weights_ (Rep a)) => Weights a
- Generic.Random.Generic: weights :: (Weights_ (Rep a), Int, ()) -> Weights a
- Generic.Random.Internal.Generic: Gen' :: Gen a -> Gen' sized a
- Generic.Random.Internal.Generic: S :: n -> S n
- Generic.Random.Internal.Generic: Tagged :: b -> Tagged a b
- Generic.Random.Internal.Generic: Z :: Z
- Generic.Random.Internal.Generic: [unGen'] :: Gen' sized a -> Gen a
- Generic.Random.Internal.Generic: [unTagged] :: Tagged a b -> b
- Generic.Random.Internal.Generic: baseCases :: BaseCases n f => Weights_ f -> Int -> Tagged n (Weighted (f p))
- Generic.Random.Internal.Generic: class BaseCases n f
- Generic.Random.Internal.Generic: class ListBaseCases n f
- Generic.Random.Internal.Generic: data S n
- Generic.Random.Internal.Generic: data Z
- Generic.Random.Internal.Generic: gArbitrarySingle :: forall sized f p c0. (GA sized f, Weights_ f ~ L c0) => Gen' sized (f p)
- Generic.Random.Internal.Generic: genericArbitrary' :: forall n a. (Generic a, GA (Sized n) (Rep a)) => n -> Weights a -> Gen a
- Generic.Random.Internal.Generic: genericArbitraryU0 :: forall n a. (Generic a, GA (Sized Z) (Rep a), UniformWeight (Weights_ (Rep a))) => Gen a
- Generic.Random.Internal.Generic: genericArbitraryU1 :: forall n a. (Generic a, GA (Sized (S Z)) (Rep a), UniformWeight (Weights_ (Rep a))) => Gen a
- Generic.Random.Internal.Generic: instance (GHC.Generics.Generic c, Generic.Random.Internal.Generic.ListBaseCases n (GHC.Generics.Rep c)) => Generic.Random.Internal.Generic.ListBaseCases (Generic.Random.Internal.Generic.S n) (GHC.Generics.K1 i c)
- Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.BaseCases n f, Generic.Random.Internal.Generic.BaseCases n g) => Generic.Random.Internal.Generic.BaseCases n (f GHC.Generics.:+: g)
- Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.GAProduct f, GHC.TypeLits.KnownNat (Generic.Random.Internal.Generic.Arity f)) => Generic.Random.Internal.Generic.GA (Generic.Random.Internal.Generic.Sized n) (GHC.Generics.M1 GHC.Generics.C c f)
- Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.GAProduct f, Generic.Random.Internal.Generic.GAProduct g) => Generic.Random.Internal.Generic.GAProduct (f GHC.Generics.:*: g)
- Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.GASum (Generic.Random.Internal.Generic.Sized n) f, Generic.Random.Internal.Generic.GASum (Generic.Random.Internal.Generic.Sized n) g, Generic.Random.Internal.Generic.BaseCases n f, Generic.Random.Internal.Generic.BaseCases n g) => Generic.Random.Internal.Generic.GA (Generic.Random.Internal.Generic.Sized n) (f GHC.Generics.:+: g)
- Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.GASum Generic.Random.Internal.Generic.Unsized f, Generic.Random.Internal.Generic.GASum Generic.Random.Internal.Generic.Unsized g) => Generic.Random.Internal.Generic.GA Generic.Random.Internal.Generic.Unsized (f GHC.Generics.:+: g)
- Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.ListBaseCases n f, Generic.Random.Internal.Generic.ListBaseCases n g) => Generic.Random.Internal.Generic.ListBaseCases n (f GHC.Generics.:*: g)
- Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.ListBaseCases n f, Generic.Random.Internal.Generic.ListBaseCases n g) => Generic.Random.Internal.Generic.ListBaseCases n (f GHC.Generics.:+: g)
- Generic.Random.Internal.Generic: instance GHC.Base.Applicative (Generic.Random.Internal.Generic.Gen' sized)
- Generic.Random.Internal.Generic: instance GHC.Base.Functor (Generic.Random.Internal.Generic.Gen' sized)
- Generic.Random.Internal.Generic: instance GHC.Base.Functor (Generic.Random.Internal.Generic.Tagged a)
- Generic.Random.Internal.Generic: instance GHC.Base.Monad (Generic.Random.Internal.Generic.Gen' sized)
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct GHC.Generics.U1
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct f => Generic.Random.Internal.Generic.GA Generic.Random.Internal.Generic.Unsized (GHC.Generics.M1 GHC.Generics.C c f)
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct f => Generic.Random.Internal.Generic.GAProduct (GHC.Generics.M1 i c f)
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct f => Generic.Random.Internal.Generic.GASum sized (GHC.Generics.M1 i c f)
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.ListBaseCases Generic.Random.Internal.Generic.Z (GHC.Generics.K1 i c)
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.ListBaseCases n GHC.Generics.U1
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.ListBaseCases n f => Generic.Random.Internal.Generic.BaseCases n (GHC.Generics.M1 i c f)
- Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.ListBaseCases n f => Generic.Random.Internal.Generic.ListBaseCases n (GHC.Generics.M1 i c f)
- Generic.Random.Internal.Generic: instance Test.QuickCheck.Arbitrary.Arbitrary c => Generic.Random.Internal.Generic.GAProduct (GHC.Generics.K1 i c)
- Generic.Random.Internal.Generic: listBaseCases :: (ListBaseCases n f, Alternative u) => Tagged n (u (f p))
- Generic.Random.Internal.Generic: newtype Gen' sized a
- Generic.Random.Internal.Generic: newtype Tagged a b
- Generic.Random.Internal.Generic: sized' :: (Int -> Gen' sized a) -> Gen' sized a
- Generic.Random.Internal.Generic: type BaseCases' n a = (Generic a, ListBaseCases n (Rep a))
+ Generic.Random: (%) :: WeightBuilder' w => W (First' w) -> Prec' w -> w
+ Generic.Random: baseCase :: BaseCase a => Gen a
+ Generic.Random: class BaseCase a
+ Generic.Random: data W (c :: Symbol)
+ Generic.Random: data Weights a
+ Generic.Random: genericArbitrary :: (Generic a, GA Unsized (Rep a)) => Weights a -> Gen a
+ Generic.Random: genericArbitrary' :: (Generic a, GA Sized (Rep a), BaseCase a) => Weights a -> Gen a
+ Generic.Random: genericArbitraryRec :: forall a. (Generic a, GA Sized (Rep a)) => Weights a -> Gen a
+ Generic.Random: genericArbitrarySingle :: (Generic a, GA Unsized (Rep a), Weights_ (Rep a) ~ L c0) => Gen a
+ Generic.Random: genericArbitraryU :: (Generic a, GA Unsized (Rep a), UniformWeight_ (Rep a)) => Gen a
+ Generic.Random: genericArbitraryU' :: (Generic a, GA Sized (Rep a), BaseCase a, UniformWeight_ (Rep a)) => Gen a
+ Generic.Random: uniform :: UniformWeight_ (Rep a) => Weights a
+ Generic.Random: weights :: (Weights_ (Rep a), Int, ()) -> Weights a
+ Generic.Random: withBaseCase :: Gen a -> Gen a -> Gen a
+ Generic.Random.Internal.BaseCase: baseCase :: BaseCase a => Gen a
+ Generic.Random.Internal.BaseCase: baseCaseSearch :: BaseCaseSearch a z y e => prox y -> proxy '(z, e) -> IfM y Gen Proxy a
+ Generic.Random.Internal.BaseCase: baseCaseSearching :: BaseCaseSearching a z => proxy '(z, a) -> Gen a
+ Generic.Random.Internal.BaseCase: baseCaseSearching_ :: BaseCaseSearching_ a z y => proxy y -> proxy2 '(z, a) -> IfM y Gen Proxy a -> Gen a
+ Generic.Random.Internal.BaseCase: class BaseCase a
+ Generic.Random.Internal.BaseCase: class BaseCaseSearch (a :: *) (z :: Nat) (y :: Maybe Nat) (e :: *)
+ Generic.Random.Internal.BaseCase: class BaseCaseSearching a z
+ Generic.Random.Internal.BaseCase: class BaseCaseSearching_ a z y
+ Generic.Random.Internal.BaseCase: class Alternative (IfM y Weighted Proxy) => GBCS (f :: k -> *) (z :: Nat) (y :: Maybe Nat) (e :: *)
+ Generic.Random.Internal.BaseCase: class Alternative (IfM (yf &&? yg) Weighted Proxy) => GBCSProduct f g z e yf yg
+ Generic.Random.Internal.BaseCase: class Alternative (IfM (yf ||? yg) Weighted Proxy) => GBCSSum f g z e yf yg
+ Generic.Random.Internal.BaseCase: class GBCSSumCompare f g z e o
+ Generic.Random.Internal.BaseCase: class GBaseCaseSearch a z y e
+ Generic.Random.Internal.BaseCase: class IsMaybe b
+ Generic.Random.Internal.BaseCase: gBaseCaseSearch :: GBaseCaseSearch a z y e => prox y -> proxy '(z, e) -> IfM y Gen Proxy a
+ Generic.Random.Internal.BaseCase: gbcs :: GBCS f z y e => prox y -> proxy '(z, e) -> IfM y Weighted Proxy (f p)
+ Generic.Random.Internal.BaseCase: gbcsProduct :: GBCSProduct f g z e yf yg => prox '(yf, yg) -> proxy '(z, e) -> IfM yf Weighted Proxy (f p) -> IfM yg Weighted Proxy (g p) -> IfM (yf &&? yg) Weighted Proxy ((f :*: g) p)
+ Generic.Random.Internal.BaseCase: gbcsSum :: GBCSSum f g z e yf yg => prox '(yf, yg) -> proxy '(z, e) -> IfM yf Weighted Proxy (f p) -> IfM yg Weighted Proxy (g p) -> IfM (yf ||? yg) Weighted Proxy ((f :+: g) p)
+ Generic.Random.Internal.BaseCase: gbcsSumCompare :: GBCSSumCompare f g z e o => proxy0 o -> proxy '(z, e) -> Weighted (f p) -> Weighted (g p) -> Weighted ((f :+: g) p)
+ Generic.Random.Internal.BaseCase: genericArbitrary' :: (Generic a, GA Sized (Rep a), BaseCase a) => Weights a -> Gen a
+ Generic.Random.Internal.BaseCase: genericArbitraryU' :: (Generic a, GA Sized (Rep a), BaseCase a, UniformWeight_ (Rep a)) => Gen a
+ Generic.Random.Internal.BaseCase: ifM :: IsMaybe b => proxy b -> c a -> d a -> IfM b c d a
+ Generic.Random.Internal.BaseCase: ifMmap :: IsMaybe b => proxy b -> (c a -> c' a') -> (d a -> d' a') -> IfM b c d a -> IfM b c' d' a'
+ Generic.Random.Internal.BaseCase: instance (GHC.Generics.Generic a, Generic.Random.Internal.BaseCase.GBCS (GHC.Generics.Rep a) z y e, Generic.Random.Internal.BaseCase.IsMaybe y) => Generic.Random.Internal.BaseCase.GBaseCaseSearch a z y e
+ Generic.Random.Internal.BaseCase: instance (Generic.Random.Internal.BaseCase.BaseCaseSearch a z y a, Generic.Random.Internal.BaseCase.BaseCaseSearching_ a z y) => Generic.Random.Internal.BaseCase.BaseCaseSearching a z
+ Generic.Random.Internal.BaseCase: instance (Generic.Random.Internal.BaseCase.BaseCaseSearch c (z GHC.TypeLits.- 1) y e, (z Generic.Random.Internal.BaseCase.== 0) ~ 'GHC.Types.False, GHC.Base.Alternative (Generic.Random.Internal.BaseCase.IfM y Generic.Random.Internal.Generic.Weighted Data.Proxy.Proxy), Generic.Random.Internal.BaseCase.IsMaybe y) => Generic.Random.Internal.BaseCase.GBCS (GHC.Generics.K1 i c) z y e
+ Generic.Random.Internal.BaseCase: instance (Generic.Random.Internal.BaseCase.GBCSProduct f g z e yf yg, Generic.Random.Internal.BaseCase.GBCS f z yf e, Generic.Random.Internal.BaseCase.GBCS g z yg e, y ~ (yf Generic.Random.Internal.BaseCase.&&? yg)) => Generic.Random.Internal.BaseCase.GBCS (f GHC.Generics.:*: g) z y e
+ Generic.Random.Internal.BaseCase: instance (Generic.Random.Internal.BaseCase.GBCSSum f g z e yf yg, Generic.Random.Internal.BaseCase.GBCS f z yf e, Generic.Random.Internal.BaseCase.GBCS g z yg e, y ~ (yf Generic.Random.Internal.BaseCase.||? yg)) => Generic.Random.Internal.BaseCase.GBCS (f GHC.Generics.:+: g) z y e
+ Generic.Random.Internal.BaseCase: instance Generic.Random.Internal.BaseCase.BaseCaseSearching a (z GHC.TypeLits.+ 1) => Generic.Random.Internal.BaseCase.BaseCaseSearching_ a z 'GHC.Base.Nothing
+ Generic.Random.Internal.BaseCase: instance Generic.Random.Internal.BaseCase.BaseCaseSearching a 0 => Generic.Random.Internal.BaseCase.BaseCase a
+ Generic.Random.Internal.BaseCase: instance Generic.Random.Internal.BaseCase.GBCS f z y e => Generic.Random.Internal.BaseCase.GBCS (GHC.Generics.M1 i c f) z y e
+ Generic.Random.Internal.BaseCase: instance Generic.Random.Internal.BaseCase.GBaseCaseSearch a z y e => Generic.Random.Internal.BaseCase.BaseCaseSearch a z y e
+ Generic.Random.Internal.BaseCase: instance Generic.Random.Internal.BaseCase.IsMaybe 'GHC.Base.Nothing
+ Generic.Random.Internal.BaseCase: instance forall k (f :: k -> GHC.Types.*) e (y :: GHC.Base.Maybe GHC.Types.Nat) (z :: GHC.Types.Nat). ((TypeError ...), GHC.Base.Alternative (Generic.Random.Internal.BaseCase.IfM y Generic.Random.Internal.Generic.Weighted Data.Proxy.Proxy)) => Generic.Random.Internal.BaseCase.GBCS f z y e
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k) (m :: GHC.Types.Nat) (n :: GHC.Types.Nat). Generic.Random.Internal.BaseCase.GBCSProduct f g z e ('GHC.Base.Just m) ('GHC.Base.Just n)
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k) (m :: GHC.Types.Nat) (n :: GHC.Types.Nat). Generic.Random.Internal.BaseCase.GBCSSumCompare f g z e (GHC.TypeLits.CmpNat m n) => Generic.Random.Internal.BaseCase.GBCSSum f g z e ('GHC.Base.Just m) ('GHC.Base.Just n)
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k) (m :: GHC.Types.Nat). Generic.Random.Internal.BaseCase.GBCSSum f g z e ('GHC.Base.Just m) 'GHC.Base.Nothing
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k) (n :: GHC.Types.Nat). Generic.Random.Internal.BaseCase.GBCSSum f g z e 'GHC.Base.Nothing ('GHC.Base.Just n)
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k). Generic.Random.Internal.BaseCase.GBCSSum f g z e 'GHC.Base.Nothing 'GHC.Base.Nothing
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k). Generic.Random.Internal.BaseCase.GBCSSumCompare f g z e 'GHC.Types.EQ
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k). Generic.Random.Internal.BaseCase.GBCSSumCompare f g z e 'GHC.Types.GT
+ Generic.Random.Internal.BaseCase: instance forall k k1 (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k). Generic.Random.Internal.BaseCase.GBCSSumCompare f g z e 'GHC.Types.LT
+ Generic.Random.Internal.BaseCase: instance forall k k1 (yf :: GHC.Base.Maybe GHC.Types.Nat) (yg :: GHC.Base.Maybe GHC.Types.Nat) (f :: GHC.Types.* -> *) (g :: GHC.Types.* -> *) (z :: k1) (e :: k). (yf Generic.Random.Internal.BaseCase.&&? yg) ~ 'GHC.Base.Nothing => Generic.Random.Internal.BaseCase.GBCSProduct f g z e yf yg
+ Generic.Random.Internal.BaseCase: instance forall t (t1 :: t). Generic.Random.Internal.BaseCase.IsMaybe ('GHC.Base.Just t1)
+ Generic.Random.Internal.BaseCase: instance forall t k a (z :: k) (m :: t). Generic.Random.Internal.BaseCase.BaseCaseSearching_ a z ('GHC.Base.Just m)
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch () z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Integer.Type.Integer z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Types.Bool z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Types.Char z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Types.Double z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Types.Float z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Types.Int z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Types.Ordering z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch GHC.Types.Word z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.BaseCaseSearch [a] z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Just 0 => Generic.Random.Internal.BaseCase.GBCS GHC.Generics.U1 z y e
+ Generic.Random.Internal.BaseCase: instance y ~ 'GHC.Base.Nothing => Generic.Random.Internal.BaseCase.GBCS (GHC.Generics.K1 i c) 0 y e
+ Generic.Random.Internal.BaseCase: type (==) m n = IsEQ (CmpNat m n)
+ Generic.Random.Internal.BaseCase: type Max m n = MaxOf (CmpNat m n) m n
+ Generic.Random.Internal.BaseCase: type Min m n = MinOf (CmpNat m n) m n
+ Generic.Random.Internal.BaseCase: withBaseCase :: Gen a -> Gen a -> Gen a
+ Generic.Random.Internal.Generic: (%.) :: WeightBuilder a => W (First a) -> Prec a r -> (a, Int, r)
+ Generic.Random.Internal.Generic: class GAProduct' f
+ Generic.Random.Internal.Generic: class UniformWeight (Weights_ f) => UniformWeight_ f
+ Generic.Random.Internal.Generic: class WeightBuilder' w
+ Generic.Random.Internal.Generic: gaProduct' :: GAProduct' f => Gen (f p)
+ Generic.Random.Internal.Generic: genericArbitraryRec :: forall a. (Generic a, GA Sized (Rep a)) => Weights a -> Gen a
+ Generic.Random.Internal.Generic: genericArbitrarySingle :: (Generic a, GA Unsized (Rep a), Weights_ (Rep a) ~ L c0) => Gen a
+ Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.GAProduct' f, GHC.TypeLits.KnownNat (Generic.Random.Internal.Generic.Arity f)) => Generic.Random.Internal.Generic.GAProduct Generic.Random.Internal.Generic.Sized f
+ Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.GAProduct' f, Generic.Random.Internal.Generic.GAProduct' g) => Generic.Random.Internal.Generic.GAProduct' (f GHC.Generics.:*: g)
+ Generic.Random.Internal.Generic: instance (Generic.Random.Internal.Generic.GASum sized f, Generic.Random.Internal.Generic.GASum sized g) => Generic.Random.Internal.Generic.GA sized (f GHC.Generics.:+: g)
+ Generic.Random.Internal.Generic: instance (TypeError ...) => Generic.Random.Internal.Generic.GA sized f
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct Generic.Random.Internal.Generic.Sized GHC.Generics.U1
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct sized f => Generic.Random.Internal.Generic.GA sized (GHC.Generics.M1 GHC.Generics.C c f)
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct sized f => Generic.Random.Internal.Generic.GASum sized (GHC.Generics.M1 i c f)
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct' GHC.Generics.U1
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct' f => Generic.Random.Internal.Generic.GAProduct Generic.Random.Internal.Generic.Unsized f
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.GAProduct' f => Generic.Random.Internal.Generic.GAProduct' (GHC.Generics.M1 i c f)
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.UniformWeight (Generic.Random.Internal.Generic.Weights_ f) => Generic.Random.Internal.Generic.UniformWeight_ f
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.WeightBuilder (Generic.Random.Internal.Generic.Weights_ (GHC.Generics.Rep a)) => Generic.Random.Internal.Generic.WeightBuilder' (Generic.Random.Internal.Generic.Weights a)
+ Generic.Random.Internal.Generic: instance Generic.Random.Internal.Generic.WeightBuilder a => Generic.Random.Internal.Generic.WeightBuilder' (a, GHC.Types.Int, r)
+ Generic.Random.Internal.Generic: instance Test.QuickCheck.Arbitrary.Arbitrary c => Generic.Random.Internal.Generic.GAProduct' (GHC.Generics.K1 i c)
+ Generic.Random.Internal.Generic: liftGen :: Gen a -> Weighted a
- Generic.Random.Internal.Generic: (%) :: WeightBuilder a => W (First a) -> Prec a r -> (a, Int, r)
+ Generic.Random.Internal.Generic: (%) :: WeightBuilder' w => W (First' w) -> Prec' w -> w
- Generic.Random.Internal.Generic: class GAProduct f
+ Generic.Random.Internal.Generic: class GAProduct sized f
- Generic.Random.Internal.Generic: data Sized n
+ Generic.Random.Internal.Generic: data Sized
- Generic.Random.Internal.Generic: ga :: GA sized f => Weights_ f -> Int -> Gen' sized (f p)
+ Generic.Random.Internal.Generic: ga :: GA sized f => proxy sized -> Weights_ f -> Int -> Gen (f p)
- Generic.Random.Internal.Generic: gaProduct :: GAProduct f => Gen (f p)
+ Generic.Random.Internal.Generic: gaProduct :: GAProduct sized f => proxy sized -> Gen (f p)
- Generic.Random.Internal.Generic: gaSum :: GASum sized f => Int -> Weights_ f -> Gen' sized (f p)
+ Generic.Random.Internal.Generic: gaSum :: GASum sized f => proxy sized -> Int -> Weights_ f -> Gen (f p)
- Generic.Random.Internal.Generic: gaSum' :: GASum sized f => Weights_ f -> Int -> Gen' sized (f p)
+ Generic.Random.Internal.Generic: gaSum' :: GASum sized f => proxy sized -> Weights_ f -> Int -> Gen (f p)
- Generic.Random.Internal.Generic: genericArbitrary :: forall a. (Generic a, GA Unsized (Rep a)) => Weights a -> Gen a
+ Generic.Random.Internal.Generic: genericArbitrary :: (Generic a, GA Unsized (Rep a)) => Weights a -> Gen a
- Generic.Random.Internal.Generic: genericArbitraryU :: forall a. (Generic a, GA Unsized (Rep a), UniformWeight (Weights_ (Rep a))) => Gen a
+ Generic.Random.Internal.Generic: genericArbitraryU :: (Generic a, GA Unsized (Rep a), UniformWeight_ (Rep a)) => Gen a
- Generic.Random.Internal.Generic: uniform :: UniformWeight (Weights_ (Rep a)) => Weights a
+ Generic.Random.Internal.Generic: uniform :: UniformWeight_ (Rep a) => Weights a

Files

CHANGELOG.md view
@@ -1,7 +1,21 @@+https://github.com/Lysxia/generic-random/blob/master/changelog.md++# 1.0.0.0++- Make the main module `Generic.Random`+- Rework generic base case generation+  + You can explicitly provide a trivial generator (e.g., returning a+    nullary constructor) using `withBaseCase`+  + Generically derive `BaseCaseSearch` and let `BaseCase` find small+    values, no depth parameter must be specified anymore+- Add `genericArbitrarySingle`, `genericArbitraryRec`, `genericArbitraryU'`+- Deprecate `weights`+- Fixed bug with `genericArbitrary'` not dividing the size parameter+ # 0.5.0.0  - Turn off dependency on boltzmann-samplers by default-- Add genericArbitraryU, genericArbitraryU0 and genericArbitraryU1+- Add `genericArbitraryU`, `genericArbitraryU0` and `genericArbitraryU1` - Compatible with GHC 7.8.4 and GHC 7.10.3  # 0.4.1.0@@ -17,5 +31,5 @@ # 0.3.0.0  - Support GHC 7.10.3-- Replace TypeApplications with ad-hoc data types in-  genericArbitraryFrequency'/genericArbitrary'+- Replace `TypeApplications` with ad-hoc data types in+  `genericArbitraryFrequency'`/`genericArbitrary'`
README.md view
@@ -1,20 +1,23 @@ Generic random generators [![Hackage](https://img.shields.io/hackage/v/generic-random.svg)](https://hackage.haskell.org/package/generic-random) [![Build Status](https://travis-ci.org/Lysxia/generic-random.svg)](https://travis-ci.org/Lysxia/generic-random) ========================= -Say goodbye to `Constructor <$> arbitrary <*> arbitrary <*> arbitrary`-boilerplate.+Derive simple random generators for [QuickCheck](https://hackage.haskell.org/package/QuickCheck) using generics. +Example+-------+ ```haskell     {-# LANGUAGE DeriveGeneric #-} -    import GHC.Generics ( Generic )+    import GHC.Generics (Generic)     import Test.QuickCheck-    import Generic.Random.Generic+    import Generic.Random      data Tree a = Leaf | Node (Tree a) a (Tree a)       deriving (Show, Generic)      instance Arbitrary a => Arbitrary (Tree a) where-      arbitrary = genericArbitrary' Z uniform+      arbitrary = genericArbitraryRec uniform `withBaseCase` return Leaf      -- Equivalent to     -- > arbitrary =@@ -24,14 +27,18 @@     -- >     else     -- >       oneof     -- >         [ return Leaf-    -- >         , Node <$> arbitrary <*> arbitrary <*> arbitrary+    -- >         , resize (n `div` 3) $+    -- >             Node <$> arbitrary <*> arbitrary <*> arbitrary     -- >         ]      main = sample (arbitrary :: Gen (Tree ())) ``` -- User-specified distribution of constructors, with a compile-time check that-  weights have been specified for all constructors.-- A simple (optional) strategy to ensure termination: `Test.QuickCheck.Gen`'s-  size parameter decreases at every recursive `genericArbitrary'` call; when it-  reaches zero, sample directly from a finite set of finite values.+Features+--------++- User-specified distribution of constructors.+- A simple (optional) strategy to ensure termination for recursive types:+  using `genericArbitrary'`, `Test.QuickCheck.Gen`'s size parameter decreases+  at every recursive call; when it reaches zero, sample directly from a+  trivially terminating generator.
generic-random.cabal view
@@ -1,5 +1,5 @@ name:                generic-random-version:             0.5.0.0+version:             1.0.0.0 synopsis:            Generic random generators description:         Please see the README. homepage:            http://github.com/lysxia/generic-random@@ -12,31 +12,32 @@ build-type:          Simple extra-source-files:  README.md CHANGELOG.md cabal-version:       >=1.10-tested-with:         GHC == 8.0.1--flag boltzmann-  Description:-    Dependency on boltzmann-samplers for backwards compatibility.-  Manual:  False-  Default: False+tested-with:         GHC == 8.0.1, GHC == 8.2.1  library   hs-source-dirs:      src   exposed-modules:+    Generic.Random     Generic.Random.Generic+    Generic.Random.Internal.BaseCase     Generic.Random.Internal.Generic+    Generic.Random.Tutorial   build-depends:-    base >= 4.7 && < 4.10,+    base >= 4.7 && < 4.11,     QuickCheck-  if flag(boltzmann)-    exposed-modules:-      Generic.Random.Boltzmann-      Generic.Random.Data-    build-depends:-      boltzmann-samplers <= 0.2   default-language:    Haskell2010   ghc-options: -Wall -fno-warn-name-shadowing  source-repository head   type:     git   location: https://github.com/lysxia/generic-random++test-suite unit+  Hs-source-dirs:  test+  Main-is:         Unit.hs+  Build-depends:+      base,+      QuickCheck,+      generic-random+  Type: exitcode-stdio-1.0+  Default-language: Haskell2010
+ src/Generic/Random.hs view
@@ -0,0 +1,32 @@+-- | Simple "GHC.Generics"-based 'arbitrary' generators.+--+-- For more information:+--+-- - "Generic.Random.Tutorial"+-- - https://byorgey.wordpress.com/2016/09/20/the-generic-random-library-part-1-simple-generic-arbitrary-instances/++module Generic.Random+  (+    -- * Arbitrary implementations+    genericArbitrary+  , genericArbitraryU+  , genericArbitrarySingle+  , genericArbitrary'+  , genericArbitraryU'+  , genericArbitraryRec++    -- * Specifying finite distributions+  , Weights+  , W+  , (%)+  , uniform++    -- * Base cases for recursive types+  , withBaseCase+  , BaseCase (..)++  , weights+  ) where++import Generic.Random.Internal.BaseCase+import Generic.Random.Internal.Generic
− src/Generic/Random/Boltzmann.hs
@@ -1,7 +0,0 @@--module Generic.Random.Boltzmann-  {-# DEPRECATED "Directly use \"Boltzmann.Species\" from @boltzmann-samplers@ instead." #-}-  ( module Boltzmann.Species-  ) where--import Boltzmann.Species
− src/Generic/Random/Data.hs
@@ -1,6 +0,0 @@-module Generic.Random.Data-  {-# DEPRECATED "Directly use \"Boltzmann.Data\" from @boltzmann-samplers@ instead." #-}-  ( module Boltzmann.Data-  ) where--import Boltzmann.Data
src/Generic/Random/Generic.hs view
@@ -1,213 +1,5 @@--- | Simple 'GHC.Generics'-based 'arbitrary' generators.------ Here is an example. Define your type.------ @--- data Tree a = Leaf a | Node (Tree a) (Tree a)---   deriving Generic--- @------ Pick an 'arbitrary' implementation.------ @--- instance Arbitrary a => Arbitrary (Tree a) where---   arbitrary = 'genericArbitrary' ('weights' (9 '%' 8 '%' ()))--- @------ @arbitrary :: 'Gen' (Tree a)@ picks a @Leaf@ with probability 9\/17, or a--- @Node@ with probability 8\/17, and recursively fills their fields with--- @arbitrary@.------ == Distribution of constructors------ The distribution of constructors can be specified using 'weights' applied to--- a special list of /weights/ in the same order as the data type definition.--- This assigns to each constructor a probability proportional to its weight;--- in other words, @p_C = weight_C / sumOfWeights@.------ The list of weights is built up with the @('%')@ operator as a cons, and using--- the unit @()@ as the empty list, in the order corresponding to the data type--- definition. The uniform distribution can be obtained with 'uniform'.------ === Example------ For @Tree@, 'genericArbitrary' produces code equivalent to the following:------ @--- 'genericArbitrary' :: Arbitrary a => 'Weights' (Tree a) -> Gen (Tree a)--- 'genericArbitrary' ('weighted' (x '%' y '%' ())) =---   frequency---     [ (x, Leaf \<$\> arbitrary)---     , (y, Node \<$\> arbitrary \<*\> arbitrary)---     ]--- @------ === Uniform distribution------ You can specify the uniform distribution (all weights equal) with 'uniform'.--- 'genericArbitraryU' is available as a shorthand for--- @'genericArbitrary' 'uniform'@.------ Note that for many types, a uniform distribution tends to produce big--- values. For instance for @Tree a@, generated values are finite but the--- __average__ number of @Leaf@ and @Node@ constructors is __infinite__.------ === Checked weights------ /GHC 8.0.1 and above only./------ The weights actually have type @'W' \"ConstructorName\"@ (just a newtype--- around 'Int'), so that you can annotate a weight with its corresponding--- constructor, and it will be checked that you got the order right.------ This will type-check.------ @--- 'weighted' ((x :: 'W' \"Leaf\") '%' (y :: 'W' \"Node\") '%' ()) :: 'Weights' (Tree a)--- 'weighted' (x '%' (y :: 'W' \"Node\") '%' ()) :: 'Weights' (Tree a)--- @------ This will not: the first requires an order of constructors different from--- the definition of the @Tree@ type; the second doesn't have the right number--- of weights.------ @--- 'weighted' ((x :: 'W' \"Node\") '%' y '%' ()) :: 'Weights' (Tree a)--- 'weighted' (x '%' y '%' z '%' ()) :: 'Weights' (Tree a)--- @------ == Ensuring termination------ As was just mentioned, one must be careful with recursive types--- to avoid producing extremely large values.------ The alternative 'genericArbitrary'' implements a simple strategy to keep--- values at reasonable sizes: the size parameter of 'Gen' is divided among the--- fields of the chosen constructor. When it reaches zero, the generator--- selects a finite term whenever it can find any of the given type.  This--- generally ensures that the number of constructors remains close to the--- initial size parameter passed to 'Gen'.------ A natural number @n@ determines the maximum /depth/ of terms that can be--- used to end recursion.--- It is encoded using @'Z' :: 'Z'@ and @'S' :: n -> 'S' n@.------ @--- 'genericArbitrary'' n ('weights' (...))--- @------ With @n = 'Z'@, the generator looks for a simple nullary constructor.  If none--- exist at the current type, as is the case for our @Tree@ type, it carries on--- as in 'genericArbitrary'.------ @--- 'genericArbitrary'' 'Z' :: Arbitrary a => 'Weights' (Tree a) -> Gen (Tree a)--- 'genericArbitrary'' 'Z' ('weights' (x '%' y '%' ())) =---   frequency---     [ (x, Leaf \<$\> arbitrary)---     , (y, scale (\`div\` 2) $ Node \<$\> arbitrary \<*\> arbitrary)---     -- 2 because Node is 2-ary.---     ]--- @------ Here is another example with nullary constructors:------ @--- data Tree' = Leaf1 | Leaf2 | Node3 Tree' Tree' Tree'---   deriving Generic------ instance Arbitrary Tree' where---   arbitrary = 'genericArbitrary'' 'Z' ('weights' (1 '%' 2 '%' 3 '%' ()))--- @------ Here, @'genericArbitrary'' 'Z'@ is equivalent to:------ @--- 'genericArbitrary'' 'Z' :: 'Weights' Tree' -> Gen Tree'--- 'genericArbitrary'' 'Z' ('weights' (x '%' y '%' z '%' ())) =---   sized $ \n ->---     if n == 0 then---       -- If the size parameter is zero, the non-nullary alternative is discarded.---       frequency $---         [ (x, return Leaf1)---         , (y, return Leaf2)---         ]---     else---       frequency $---         [ (x, return Leaf1)---         , (y, return Leaf2)---         , (z, resize (n \`div\` 3) node)  -- 3 because Node3 is 3-ary---         ]---   where---     node = Node3 \<$\> arbitrary \<*\> arbitrary \<*\> arbitrary--- @------ To increase the chances of termination when no nullary constructor is directly--- available, such as in @Tree@, we can pass a larger depth @n@. The effectiveness--- of this parameter depends on the concrete type the generator is used for.------ For instance, if we want to generate a value of type @Tree ()@, there is a--- value of depth 1 (represented by @'S' 'Z'@) that we can use to end--- recursion: @Leaf ()@.------ @--- 'genericArbitrary'' ('S' 'Z') :: 'Weights' (Tree ()) -> Gen (Tree ())--- 'genericArbitrary'' ('S' 'Z') ('weights' (x '%' y '%' ())) =---   sized $ \n ->---     if n == 0 then---       return (Leaf ())---     else---       frequency---         [ (x, Leaf \<$\> arbitrary)---         , (y, scale (\`div\` 2) $ Node \<$\> arbitrary \<*\> arbitrary)---         ]--- @------ Because the argument of @Tree@ must be inspected in order to discover--- values of type @Tree ()@, we incur some extra constraints if we want--- polymorphism.------ @UndecidableInstances@ is also required.------ @--- instance (Arbitrary a, Generic a, 'ListBaseCases' 'Z' (Rep a))---   => Arbitrary (Tree a) where---   arbitrary = 'genericArbitrary'' ('S' 'Z') ('weights' (1 '%' 2 '%' ()))--- @------ A synonym is provided for brevity.------ @--- instance (Arbitrary a, 'BaseCases'' Z a) => Arbitrary (Tree a) where---   arbitrary = 'genericArbitrary'' ('S' 'Z') ('weights' (1 '%' 2 '%' ()))--- @---module Generic.Random.Generic-  (-    -- * Arbitrary implementations-    genericArbitrary-  , genericArbitraryU-  , genericArbitrary'-  , genericArbitraryU0-  , genericArbitraryU1--    -- * Specifying finite distributions-  , Weights-  , W-  , weights-  , (%)-  , uniform--    -- * Type-level natural numbers-    -- $nat-  , Z (..)-  , S (..)+-- | Reexport of "Generic.Random", for backwards-compatibility. -    -- * Generic classes for finite values-  , BaseCases'-  , BaseCases-  , ListBaseCases-  ) where+module Generic.Random.Generic ( module Generic.Random ) where -import Generic.Random.Internal.Generic+import Generic.Random
+ src/Generic/Random/Internal/BaseCase.hs view
@@ -0,0 +1,320 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+#if __GLASGOW_HASKELL__ < 710+{-# LANGUAGE OverlappingInstances #-}+#endif++module Generic.Random.Internal.BaseCase where++import Control.Applicative+#if __GLASGOW_HASKELL__ >= 800+import Data.Proxy+#endif+#if __GLASGOW_HASKELL__ < 710+import Data.Word+#endif+import GHC.Generics+import GHC.TypeLits+import Test.QuickCheck++import Generic.Random.Internal.Generic++-- | Decrease size to ensure termination for+-- recursive types, looking for base cases once the size reaches 0.+--+-- > genericArbitrary' (17 % 19 % 23 % ()) :: Gen a+genericArbitrary'+  :: (Generic a, GA Sized (Rep a), BaseCase a)+  => Weights a  -- ^ List of weights for every constructor+  -> Gen a+genericArbitrary' w = genericArbitraryRec w `withBaseCase` baseCase++-- | Equivalent to @'genericArbitrary'' 'uniform'@.+--+-- > genericArbitraryU :: Gen a+genericArbitraryU'+  :: (Generic a, GA Sized (Rep a), BaseCase a, UniformWeight_ (Rep a))+  => Gen a+genericArbitraryU' = genericArbitrary' uniform++-- | Run the first generator if the size is positive.+-- Run the second if the size is zero.+--+-- > defaultGen `withBaseCase` baseCaseGen+withBaseCase :: Gen a -> Gen a -> Gen a+withBaseCase def bc = sized $ \sz ->+  if sz > 0 then def else bc+++-- | Find a base case of type @a@ with maximum depth @z@,+-- recursively using 'BaseCaseSearch' instances to search deeper levels.+--+-- @y@ is the depth of a base case, if found.+--+-- @e@ is the original type the search started with, that @a@ appears in.+-- It is used for error reporting.+class BaseCaseSearch (a :: *) (z :: Nat) (y :: Maybe Nat) (e :: *) where+  baseCaseSearch :: prox y -> proxy '(z, e) -> IfM y Gen Proxy a+++instance {-# OVERLAPPABLE #-} GBaseCaseSearch a z y e => BaseCaseSearch a z y e where+  baseCaseSearch = gBaseCaseSearch+++instance (y ~ 'Just 0) => BaseCaseSearch Char z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch Int z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch Integer z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch Float z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch Double z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch Word z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch () z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch Bool z y e where+  baseCaseSearch _ _ = arbitrary++instance (y ~ 'Just 0) => BaseCaseSearch [a] z y e where+  baseCaseSearch _ _ = return []++instance (y ~ 'Just 0) => BaseCaseSearch Ordering z y e where+  baseCaseSearch _ _ = arbitrary++-- Either and (,) use Generics+++class BaseCaseSearching_ a z y where+  baseCaseSearching_ :: proxy y -> proxy2 '(z, a) -> IfM y Gen Proxy a -> Gen a++instance BaseCaseSearching_ a z ('Just m) where+  baseCaseSearching_ _ _ = id++instance BaseCaseSearching a (z + 1) => BaseCaseSearching_ a z 'Nothing where+  baseCaseSearching_ _ _ _ = baseCaseSearching (Proxy :: Proxy '(z + 1, a))++-- | Progressively increase the depth bound for 'BaseCaseSearch'.+class BaseCaseSearching a z where+  baseCaseSearching :: proxy '(z, a) -> Gen a++instance (BaseCaseSearch a z y a, BaseCaseSearching_ a z y) => BaseCaseSearching a z where+  baseCaseSearching z = baseCaseSearching_ y z (baseCaseSearch y z)+    where+      y = Proxy :: Proxy y++-- | Custom instances can override the default behavior.+class BaseCase a where+  -- | Generator of base cases.+  baseCase :: Gen a++-- | Overlappable+instance {-# OVERLAPPABLE #-} BaseCaseSearching a 0 => BaseCase a where+  baseCase = baseCaseSearching (Proxy :: Proxy '(0, a))+++type family IfM (b :: Maybe t) (c :: k) (d :: k) :: k+type instance IfM ('Just t) c d = c+type instance IfM 'Nothing c d = d++type (==) m n = IsEQ (CmpNat m n)++type family IsEQ (e :: Ordering) :: Bool+type instance IsEQ 'EQ = 'True+type instance IsEQ 'GT = 'False+type instance IsEQ 'LT = 'False++type family (||?) (b :: Maybe Nat) (c :: Maybe Nat) :: Maybe Nat+type instance 'Just m ||? 'Just n = 'Just (Min m n)+type instance m ||? 'Nothing = m+type instance 'Nothing ||? n = n++type family (&&?) (b :: Maybe Nat) (c :: Maybe Nat) :: Maybe Nat+type instance 'Just m &&? 'Just n = 'Just (Max m n)+type instance m &&? 'Nothing = 'Nothing+type instance 'Nothing &&? n = 'Nothing++type Max m n = MaxOf (CmpNat m n) m n++type family MaxOf (e :: Ordering) (m :: k) (n :: k) :: k+type instance MaxOf 'GT m n = m+type instance MaxOf 'EQ m n = m+type instance MaxOf 'LT m n = n++type Min m n = MinOf (CmpNat m n) m n++type family MinOf (e :: Ordering) (m :: k) (n :: k) :: k+type instance MinOf 'GT m n = n+type instance MinOf 'EQ m n = n+type instance MinOf 'LT m n = m++class Alternative (IfM y Weighted Proxy)+  => GBCS (f :: k -> *) (z :: Nat) (y :: Maybe Nat) (e :: *) where+  gbcs :: prox y -> proxy '(z, e) -> IfM y Weighted Proxy (f p)++instance GBCS f z y e => GBCS (M1 i c f) z y e where+  gbcs y z = fmap M1 (gbcs y z)++instance+  ( GBCSSum f g z e yf yg+  , GBCS f z yf e+  , GBCS g z yg e+  , y ~ (yf ||? yg)+  ) => GBCS (f :+: g) z y e where+  gbcs _ z = gbcsSum (Proxy :: Proxy '(yf, yg)) z+    (gbcs (Proxy :: Proxy yf) z)+    (gbcs (Proxy :: Proxy yg) z)++class Alternative (IfM (yf ||? yg) Weighted Proxy) => GBCSSum f g z e yf yg where+  gbcsSum+    :: prox '(yf, yg)+    -> proxy '(z, e)+    -> IfM yf Weighted Proxy (f p)+    -> IfM yg Weighted Proxy (g p)+    -> IfM (yf ||? yg) Weighted Proxy ((f :+: g) p)++instance GBCSSum f g z e 'Nothing 'Nothing where+  gbcsSum _ _ _ _ = Proxy++instance GBCSSum f g z e ('Just m) 'Nothing where+  gbcsSum _ _ f _ = fmap L1 f++instance GBCSSum f g z e 'Nothing ('Just n) where+  gbcsSum _ _ _ g = fmap R1 g++instance GBCSSumCompare f g z e (CmpNat m n)+  => GBCSSum f g z e ('Just m) ('Just n) where+  gbcsSum _ = gbcsSumCompare (Proxy :: Proxy (CmpNat m n))++class GBCSSumCompare f g z e o where+  gbcsSumCompare+    :: proxy0 o+    -> proxy '(z, e)+    -> Weighted (f p)+    -> Weighted (g p)+    -> Weighted ((f :+: g) p)++instance GBCSSumCompare f g z e 'EQ where+  gbcsSumCompare _ _ f g = fmap L1 f <|> fmap R1 g++instance GBCSSumCompare f g z e 'LT where+  gbcsSumCompare _ _ f _ = fmap L1 f++instance GBCSSumCompare f g z e 'GT where+  gbcsSumCompare _ _ _ g = fmap R1 g++instance+  ( GBCSProduct f g z e yf yg+  , GBCS f z yf e+  , GBCS g z yg e+  , y ~ (yf &&? yg)+  ) => GBCS (f :*: g) z y e where+  gbcs _ z = gbcsProduct (Proxy :: Proxy '(yf, yg)) z+    (gbcs (Proxy :: Proxy yf) z)+    (gbcs (Proxy :: Proxy yg) z)++class Alternative (IfM (yf &&? yg) Weighted Proxy) => GBCSProduct f g z e yf yg where+  gbcsProduct+    :: prox '(yf, yg)+    -> proxy '(z, e)+    -> IfM yf Weighted Proxy (f p)+    -> IfM yg Weighted Proxy (g p)+    -> IfM (yf &&? yg) Weighted Proxy ((f :*: g) p)++instance {-# OVERLAPPABLE #-} ((yf &&? yg) ~ 'Nothing) => GBCSProduct f g z e yf yg where+  gbcsProduct _ _ _ _ = Proxy++instance GBCSProduct f g z e ('Just m) ('Just n) where+  gbcsProduct _ _ f g = liftA2 (:*:) f g++class IsMaybe b where+  ifMmap :: proxy b -> (c a -> c' a') -> (d a -> d' a') -> IfM b c d a -> IfM b c' d' a'+  ifM :: proxy b -> c a -> d a -> IfM b c d a++instance IsMaybe ('Just t) where+  ifMmap _ f _ a = f a+  ifM _ f _ = f++instance IsMaybe 'Nothing where+  ifMmap _ _ g a = g a+  ifM _ _ g = g++instance {-# OVERLAPPABLE #-}+  ( BaseCaseSearch c (z - 1) y e+  , (z == 0) ~ 'False+  , Alternative (IfM y Weighted Proxy)+  , IsMaybe y+  ) => GBCS (K1 i c) z y e where+  gbcs y _ =+    fmap K1+      (ifMmap y+        liftGen+        (id :: Proxy c -> Proxy c)+        (baseCaseSearch y (Proxy :: Proxy '(z - 1, e))))++instance (y ~ 'Nothing) => GBCS (K1 i c) 0 y e where+  gbcs _ _ = empty++instance (y ~ 'Just 0) => GBCS U1 z y e where+  gbcs _ _ = pure U1++#if __GLASGOW_HASKELL__ >= 800+instance {-# INCOHERENT #-}+  ( TypeError+      (     'Text "Unrecognized Rep: "+      ':<>: 'ShowType f+      ':$$: 'Text "Possible causes:"+      ':$$: 'Text "    Missing ("+      ':<>: 'ShowType (BaseCase e)+      ':<>: 'Text ") constraint"+      ':$$: 'Text "    Missing Generic instance"+    )+  , Alternative (IfM y Weighted Proxy)+  ) => GBCS f z y e where+  gbcs = error "Type error"+#endif++class GBaseCaseSearch a z y e where+  gBaseCaseSearch :: prox y -> proxy '(z, e) -> IfM y Gen Proxy a++instance (Generic a, GBCS (Rep a) z y e, IsMaybe y)+  => GBaseCaseSearch a z y e where+  gBaseCaseSearch y z = ifMmap y+    (\(Weighted (Just (g, n))) -> choose (0, n-1) >>= fmap to . g)+    (\Proxy -> Proxy)+    (gbcs y z)++#if __GLASGOW_HASKELL__ < 800+data Proxy a = Proxy++instance Functor Proxy where+  fmap _ _ = Proxy++instance Applicative Proxy where+  pure _ = Proxy+  _ <*> _ = Proxy++instance Alternative Proxy where+  empty = Proxy+  _ <|> _ = Proxy+#endif
src/Generic/Random/Internal/Generic.hs view
@@ -1,70 +1,76 @@-{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}+#if __GLASGOW_HASKELL__ < 710+{-# LANGUAGE OverlappingInstances #-}+#endif  module Generic.Random.Internal.Generic where  import Control.Applicative-import Data.Coerce import Data.Proxy+#if __GLASGOW_HASKELL__ >= 800+import GHC.Generics hiding (S)+#else import GHC.Generics hiding (S, Arity)+#endif import GHC.TypeLits import Test.QuickCheck  -- * Random generators  -- | Pick a constructor with a given distribution, and fill its fields--- recursively.+-- with recursive calls to 'arbitrary'.+--+-- === Example+--+-- > genericArbitrary (2 % 3 % 5 % ()) :: Gen a+--+-- Picks the first constructor with probability @2/10@,+-- the second with probability @3/10@, the third with probability @5/10@. genericArbitrary-  :: forall a-  .  (Generic a, GA Unsized (Rep a))+  :: (Generic a, GA Unsized (Rep a))   => Weights a  -- ^ List of weights for every constructor   -> Gen a-genericArbitrary (Weights w n) = (unGen' . fmap to) (ga w n :: Gen' Unsized (Rep a p))+genericArbitrary (Weights w n) = fmap to (ga (Proxy :: Proxy Unsized) w n) --- | Shorthand for @'genericArbitrary' 'uniform'@.+-- | Pick every constructor with equal probability.+-- Equivalent to @'genericArbitrary' 'uniform'@.+--+-- > genericArbitraryU :: Gen a genericArbitraryU-  :: forall a-  .  (Generic a, GA Unsized (Rep a), UniformWeight (Weights_ (Rep a)))+  :: (Generic a, GA Unsized (Rep a), UniformWeight_ (Rep a))   => Gen a genericArbitraryU = genericArbitrary uniform --- | Like 'genericArbitrary'', with decreasing size to ensure termination for--- recursive types, looking for base cases once the size reaches 0.-genericArbitrary'-  :: forall n a-  . (Generic a, GA (Sized n) (Rep a))-  => n-  -> Weights a  -- ^ List of weights for every constructor-  -> Gen a-genericArbitrary' _ (Weights w n) =-  (unGen' . fmap to) (ga w n :: Gen' (Sized n) (Rep a p))---- | Shorthand for @'genericArbitrary'' 'Z' 'uniform'@, using nullary--- constructors as the base cases.-genericArbitraryU0-  :: forall n a-  . (Generic a, GA (Sized Z) (Rep a), UniformWeight (Weights_ (Rep a)))+-- | 'arbitrary' for types with one constructor.+-- Equivalent to 'genericArbitraryU', with a stricter type.+--+-- > genericArbitrarySingle :: Gen a+genericArbitrarySingle+  :: (Generic a, GA Unsized (Rep a), Weights_ (Rep a) ~ L c0)   => Gen a-genericArbitraryU0 = genericArbitrary' Z uniform+genericArbitrarySingle = genericArbitraryU --- | Shorthand for @'genericArbitrary'' ('S' 'Z') 'uniform'@, using nullary--- constructors and constructors whose fields are all nullary as base cases.-genericArbitraryU1-  :: forall n a-  . (Generic a, GA (Sized (S Z)) (Rep a), UniformWeight (Weights_ (Rep a)))-  => Gen a-genericArbitraryU1 = genericArbitrary' (S Z) uniform+-- | Decrease size at every recursive call, but don't do anything different+-- at size 0.+--+-- > genericArbitraryRec (7 % 11 % 13 % ()) :: Gen a+genericArbitraryRec+  :: forall a+  . (Generic a, GA Sized (Rep a))+  => Weights a  -- ^ List of weights for every constructor+  -> Gen a+genericArbitraryRec (Weights w n) =+  fmap to (ga (Proxy :: Proxy Sized) w n :: Gen (Rep a p))  -- * Internal @@ -74,7 +80,7 @@ #if __GLASGOW_HASKELL__ >= 800   Weights_ (M1 C ('MetaCons c _i _j) _f) = L c #else-  Weights_ (M1 C _c _f) = ()+  Weights_ (M1 C _c _f) = L "" #endif  data a :| b = N a Int b@@ -86,14 +92,14 @@ -- Two ways of constructing them. -- -- @--- 'weights' (x1 '%' x2 '%' ... '%' xn '%' ()) :: 'Weights' a+-- (x1 '%' x2 '%' ... '%' xn '%' ()) :: 'Weights' a -- 'uniform' :: 'Weights' a -- @ ----- Using @weights@, there must be exactly as many weights as+-- Using @('%')@, there must be exactly as many weights as -- there are constructors. ----- 'uniform' is equivalent to @'weights' (1 '%' ... '%' 1 '%' ())@+-- 'uniform' is equivalent to @(1 '%' ... '%' 1 '%' ())@ -- (automatically fills out the right number of 1s). data Weights a = Weights (Weights_ (Rep a)) Int @@ -101,16 +107,17 @@ -- constructor for additional compile-time checking. -- -- @--- 'weights' ((9 :: 'W' \"Leaf\") '%' (8 :: 'W' \"Node\") '%' ())+-- ((9 :: 'W' \"Leaf\") '%' (8 :: 'W' \"Node\") '%' ()) -- @ newtype W (c :: Symbol) = W Int deriving Num +{-# DEPRECATED weights "Can be omitted" #-} -- | A smart constructor to specify a custom distribution. weights :: (Weights_ (Rep a), Int, ()) -> Weights a weights (w, n, ()) = Weights w n  -- | Uniform distribution.-uniform :: UniformWeight (Weights_ (Rep a)) => Weights a+uniform :: UniformWeight_ (Rep a) => Weights a uniform =   let (w, n) = uniformWeight   in Weights w n@@ -119,27 +126,45 @@   First (a :| _b) = First a   First (L c) = c +type family First' w where+  First' (Weights a) = First (Weights_ (Rep a))+  First' (a, Int, r) = First a++type family Prec' w where+  Prec' (Weights a) = Prec (Weights_ (Rep a)) ()+  Prec' (a, Int, r) = Prec a r++class WeightBuilder' w where++  -- | A binary constructor for building up trees of weights.+  (%) :: W (First' w) -> Prec' w -> w++instance WeightBuilder (Weights_ (Rep a)) => WeightBuilder' (Weights a) where+  w % prec = weights (w %. prec)++instance WeightBuilder a => WeightBuilder' (a, Int, r) where+  (%) = (%.)+ class WeightBuilder a where   type Prec a r -  -- | A binary constructor for building up trees of weights.-  (%) :: W (First a) -> Prec a r -> (a, Int, r)+  (%.) :: W (First a) -> Prec a r -> (a, Int, r)  infixr 1 %  instance WeightBuilder a => WeightBuilder (a :| b) where   type Prec (a :| b) r = Prec a (b, Int, r)-  m % prec =+  m %. prec =     let (a, n, (b, p, r)) = m % prec     in (N a n b, n + p, r)  instance WeightBuilder (L c) where   type Prec (L c) r = r-  W m % prec = (L, m, prec)+  W m %. prec = (L, m, prec)  instance WeightBuilder () where   type Prec () r = r-  W m % prec = ((), m, prec)+  W m %. prec = ((), m, prec)  class UniformWeight a where   uniformWeight :: (a, Int)@@ -158,96 +183,89 @@ instance UniformWeight () where   uniformWeight = ((), 1) -newtype Gen' sized a = Gen' { unGen' :: Gen a }-  deriving (Functor, Applicative, Monad)+class UniformWeight (Weights_ f) => UniformWeight_ f+instance UniformWeight (Weights_ f) => UniformWeight_ f -data Sized n+data Sized data Unsized -sized' :: (Int -> Gen' sized a) -> Gen' sized a-sized' g = Gen' . sized $ \sz -> unGen' (g sz)- -- | Generic Arbitrary class GA sized f where-  ga :: Weights_ f -> Int -> Gen' sized (f p)+  ga :: proxy sized -> Weights_ f -> Int -> Gen (f p)  instance GA sized f => GA sized (M1 D c f) where-  ga w n = fmap M1 (ga w n)--instance GAProduct f => GA Unsized (M1 C c f) where-  ga _ _ = (Gen' . fmap M1) gaProduct--instance (GAProduct f, KnownNat (Arity f)) => GA (Sized n) (M1 C c f) where-  ga _ _ = Gen' (sized $ \n -> resize (n `div` arity) gaProduct)-    where-      arity = fromInteger (natVal (Proxy :: Proxy (Arity f)))--instance (GASum (Sized n) f, GASum (Sized n) g, BaseCases n f, BaseCases n g)-  => GA (Sized n) (f :+: g) where-  ga w n = sized' $ \sz ->-    case unTagged (baseCases w n :: Tagged n (Weighted ((f :+: g) p))) of-      Weighted (Just (bc, n)) | sz == 0 -> Gen' (choose (0, n - 1) >>= bc)-      _ -> gaSum' w n+  ga z w n = fmap M1 (ga z w n) -instance (GASum Unsized f, GASum Unsized g) => GA Unsized (f :+: g) where+instance (GASum sized f, GASum sized g) => GA sized (f :+: g) where   ga = gaSum' -gArbitrarySingle-  :: forall sized f p c0-  .  (GA sized f, Weights_ f ~ L c0)-  => Gen' sized (f p)-gArbitrarySingle = ga L 0+instance GAProduct sized f => GA sized (M1 C c f) where+  ga z _ _ = fmap M1 (gaProduct z) -gaSum' :: GASum sized f => Weights_ f -> Int -> Gen' sized (f p)-gaSum' w n = do-  i <- Gen' $ choose (0, n-1)-  gaSum i w+#if __GLASGOW_HASKELL__ >= 800+instance {-# INCOHERENT #-}+  TypeError+    (     'Text "Unrecognized Rep: "+    ':<>: 'ShowType f+    ':$$: 'Text "Possible cause: missing Generic instance"+    )+  => GA sized f where+  ga = error "Type error"+#endif +gaSum' :: GASum sized f => proxy sized -> Weights_ f -> Int -> Gen (f p)+gaSum' z w n = do+  i <- choose (0, n-1)+  gaSum z i w+ class GASum sized f where-  gaSum :: Int -> Weights_ f -> Gen' sized (f p)+  gaSum :: proxy sized -> Int -> Weights_ f -> Gen (f p)  instance (GASum sized f, GASum sized g) => GASum sized (f :+: g) where-  gaSum i (N a n b)-    | i < n = fmap L1 (gaSum i a)-    | otherwise = fmap R1 (gaSum (i - n) b)+  gaSum z i (N a n b)+    | i < n = fmap L1 (gaSum z i a)+    | otherwise = fmap R1 (gaSum z (i - n) b) -instance GAProduct f => GASum sized (M1 i c f) where-  gaSum _ _ = Gen' gaProduct+instance GAProduct sized f => GASum sized (M1 i c f) where+  gaSum z _ _ = fmap M1 (gaProduct z)  -class GAProduct f where-  gaProduct :: Gen (f p)+class GAProduct sized f where+  gaProduct :: proxy sized -> Gen (f p) -instance GAProduct U1 where-  gaProduct = pure U1+instance GAProduct' f => GAProduct Unsized f where+  gaProduct _ = gaProduct' -instance Arbitrary c => GAProduct (K1 i c) where-  gaProduct = fmap K1 arbitrary+instance (GAProduct' f, KnownNat (Arity f)) => GAProduct Sized f where+  gaProduct _ = sized $ \n -> resize (n `div` arity) gaProduct'+    where+      arity = fromInteger (natVal (Proxy :: Proxy (Arity f))) -instance GAProduct f => GAProduct (M1 i c f) where-  gaProduct = fmap M1 gaProduct+instance {-# OVERLAPPING #-} GAProduct Sized U1 where+  gaProduct _ = pure U1 -instance (GAProduct f, GAProduct g) => GAProduct (f :*: g) where-  gaProduct = liftA2 (:*:) gaProduct gaProduct -type family Arity f :: Nat where-  Arity (f :*: g) = Arity f + Arity g-  Arity (M1 _i _c _f) = 1+class GAProduct' f where+  gaProduct' :: Gen (f p) +instance GAProduct' U1 where+  gaProduct' = pure U1 -newtype Tagged a b = Tagged { unTagged :: b }-  deriving Functor+instance Arbitrary c => GAProduct' (K1 i c) where+  gaProduct' = fmap K1 arbitrary --- $nat--- Use the 'Z' and 'S' data types to define the depths of values used--- by 'genericArbitrary'' to make generators terminate.+instance (GAProduct' f, GAProduct' g) => GAProduct' (f :*: g) where+  gaProduct' = liftA2 (:*:) gaProduct' gaProduct' --- | Zero-data Z = Z+instance GAProduct' f => GAProduct' (M1 i c f) where+  gaProduct' = fmap M1 gaProduct' --- | Successor-data S n = S n +type family Arity f :: Nat where+  Arity (f :*: g) = Arity f + Arity g+  Arity (M1 _i _c _f) = 1++ newtype Weighted a = Weighted (Maybe (Int -> Gen a, Int))   deriving Functor @@ -273,62 +291,6 @@           b (i - m)     , m + n ) -class BaseCases n f where-  baseCases :: Weights_ f -> Int -> Tagged n (Weighted (f p))--instance (BaseCases n f, BaseCases n g) => BaseCases n (f :+: g) where-  baseCases (N a m b) n =-    concat-      ((fmap . fmap) L1 (baseCases a m))-      ((fmap . fmap) R1 (baseCases b (n - m)))-    where-      concat :: Alternative u => Tagged n (u a) -> Tagged n (u a) -> Tagged n (u a)-      concat (Tagged a) (Tagged b) = Tagged (a <|> b)--instance ListBaseCases n f => BaseCases n (M1 i c f) where-  baseCases _ n = fmap reweigh listBaseCases-    where-      reweigh :: Weighted a -> Weighted a-      reweigh (Weighted h) = Weighted (fmap (\(g, _) -> (g, n)) h)---- | A @ListBaseCases n ('Rep' a)@ constraint basically provides the list of--- values of type @a@ with depth at most @n@.-class ListBaseCases n f where-  listBaseCases :: Alternative u => Tagged n (u (f p))---- | For convenience.-type BaseCases' n a = (Generic a, ListBaseCases n (Rep a))--instance ListBaseCases n U1 where-  listBaseCases = Tagged (pure U1)--instance ListBaseCases n f => ListBaseCases n (M1 i c f) where-  listBaseCases = (fmap . fmap) M1 listBaseCases--instance ListBaseCases Z (K1 i c) where-  listBaseCases = Tagged empty--instance (Generic c, ListBaseCases n (Rep c)) => ListBaseCases (S n) (K1 i c) where-  listBaseCases = (retag . (fmap . fmap) (K1 . to)) listBaseCases-    where-      retag :: Tagged n a -> Tagged (S n) a-      retag = coerce--instance (ListBaseCases n f, ListBaseCases n g) => ListBaseCases n (f :+: g) where-  listBaseCases =-    concat-      ((fmap . fmap) L1 listBaseCases)-      ((fmap . fmap) R1 listBaseCases)-    where-      concat :: Alternative u => Tagged n (u a) -> Tagged n (u a) -> Tagged n (u a)-      concat (Tagged a) (Tagged b) = Tagged (a <|> b)+liftGen :: Gen a -> Weighted a+liftGen g = Weighted (Just (\_ -> g, 1)) -instance (ListBaseCases n f, ListBaseCases n g) => ListBaseCases n (f :*: g) where-  listBaseCases = liftedP listBaseCases listBaseCases-    where-      liftedP-        :: Applicative u-        => Tagged n (u (f p))-        -> Tagged n (u (g p))-        -> Tagged n (u ((f :*: g) p))-      liftedP (Tagged f) (Tagged g) = Tagged (liftA2 (:*:) f g)
+ src/Generic/Random/Tutorial.hs view
@@ -0,0 +1,183 @@+-- | Generic implementations of+-- [QuickCheck](https://hackage.haskell.org/package/QuickCheck)'s+-- @arbitrary@.+--+-- == Example+--+-- Define your type.+--+-- @+-- data Tree a = Leaf a | Node (Tree a) (Tree a)+--   deriving 'Generic'+-- @+--+-- Pick an 'arbitrary' implementation, specifying the required distribution of+-- data constructors.+--+-- @+-- instance Arbitrary a => Arbitrary (Tree a) where+--   arbitrary = 'genericArbitrary' (8 '%' 9 '%' ())+-- @+--+-- @arbitrary :: 'Gen' (Tree a)@ picks a @Leaf@ with probability 9\/17, or a+-- @Node@ with probability 8\/17, and recursively fills their fields with+-- @arbitrary@.+--+-- For @Tree@, 'genericArbitrary' produces code equivalent to the following:+--+-- @+-- 'genericArbitrary' :: Arbitrary a => 'Weights' (Tree a) -> Gen (Tree a)+-- 'genericArbitrary' (x '%' y '%' ()) =+--   frequency+--     [ (x, Leaf \<$\> arbitrary)+--     , (y, Node \<$\> arbitrary \<*\> arbitrary)+--     ]+-- @+--+-- == Distribution of constructors+--+-- The distribution of constructors can be specified as+-- a special list of /weights/ in the same order as the data type definition.+-- This assigns to each constructor a probability proportional to its weight;+-- in other words, @p_C = weight_C / sumOfWeights@.+--+-- The list of weights is built up with the @('%')@ operator as a cons, and using+-- the unit @()@ as the empty list, in the order corresponding to the data type+-- definition. The uniform distribution can be obtained with 'uniform'.+--+-- === Uniform distribution+--+-- You can specify the uniform distribution (all weights equal) with 'uniform'.+-- ('genericArbitraryU' is available as a shorthand for+-- @'genericArbitrary' 'uniform'@.)+--+-- Note that for many recursive types, a uniform distribution tends to produce+-- big or even infinite values.+--+-- === Typed weights+--+-- /GHC 8.0.1 and above only (base ≥ 4.9)./+--+-- The weights actually have type @'W' \"ConstructorName\"@ (just a newtype+-- around 'Int'), so that you can annotate a weight with its corresponding+-- constructor, and it will be checked that you got the order right.+--+-- This will type-check.+--+-- @+-- ((x :: 'W' \"Leaf\") '%' (y :: 'W' \"Node\") '%' ()) :: 'Weights' (Tree a)+-- (x '%' (y :: 'W' \"Node\") '%' ()) :: 'Weights' (Tree a)+-- @+--+-- This will not: the first requires an order of constructors different from+-- the definition of the @Tree@ type; the second doesn't have the right number+-- of weights.+--+-- @+-- ((x :: 'W' \"Node\") '%' y '%' ()) :: 'Weights' (Tree a)+-- (x '%' y '%' z '%' ()) :: 'Weights' (Tree a)+-- @+--+-- == Ensuring termination+--+-- As mentioned earlier, one must be careful with recursive types+-- to avoid producing extremely large values.+--+-- The alternative generator 'genericArbitrary'' implements a simple strategy to keep+-- values at reasonable sizes: the size parameter of 'Gen' is divided among the+-- fields of the chosen constructor. When it reaches zero, the generator+-- selects a small term of the given type. This generally ensures that the+-- number of constructors remains close to the initial size parameter passed to+-- 'Gen'.+--+-- @+-- 'genericArbitrary'' (x1 '%' ... '%' xn '%' ())+-- @+--+-- Here is an example with nullary constructors:+--+-- @+-- data Bush = Leaf1 | Leaf2 | Node3 Bush Bush Bush+--   deriving Generic+--+-- instance Arbitrary Bush where+--   arbitrary = 'genericArbitrary'' (1 '%' 2 '%' 3 '%' ())+-- @+--+-- Here, 'genericArbitrary'' is equivalent to:+--+-- @+-- 'genericArbitrary'' :: 'Weights' Bush -> Gen Bush+-- 'genericArbitrary'' (x '%' y '%' z '%' ()) =+--   sized $ \\n ->+--     if n == 0 then+--       -- If the size parameter is zero, only nullary alternatives are kept.+--       elements [Leaf1, Leaf2]+--     else+--       frequency+--         [ (x, return Leaf1)+--         , (y, return Leaf2)+--         , (z, resize (n \`div\` 3) node)  -- 3 because Node3 is 3-ary+--         ]+--   where+--     node = Node3 \<$\> arbitrary \<*\> arbitrary \<*\> arbitrary+-- @+--+-- If we want to generate a value of type @Tree ()@, there is a+-- value of depth 1 that we can use to end recursion: @Leaf ()@.+--+-- @+-- 'genericArbitrary'' :: 'Weights' (Tree ()) -> Gen (Tree ())+-- 'genericArbitrary'' (x '%' y '%' ()) =+--   sized $ \\n ->+--     if n == 0 then+--       return (Leaf ())+--     else+--       frequency+--         [ (x, Leaf \<$\> arbitrary)+--         , (y, resize (n \`div\` 2) $ Node \<$\> arbitrary \<*\> arbitrary)+--         ]+-- @+--+-- Because the argument of @Tree@ must be inspected in order to discover+-- values of type @Tree ()@, we incur some extra constraints if we want+-- polymorphism.+--+-- @+-- {-\# LANGUAGE FlexibleContexts, UndecidableInstances \#-}+--+-- instance (Arbitrary a, BaseCase (Tree a))+--   => Arbitrary (Tree a) where+--   arbitrary = 'genericArbitrary'' (1 '%' 2 '%' ())+-- @+--+-- By default, the 'BaseCase' type class looks for all values of minimal depth+-- (constructors have depth @1 + max(0, depths of fields)@).+--+-- This can easily be overriden by declaring a specialized 'BaseCase' instance,+-- such as this one:+--+-- @+-- instance Arbitrary a => 'BaseCase' (Tree a) where+--   'baseCase' = oneof [leaf, simpleNode]+--     where+--       leaf = Leaf \<$\> arbitrary+--       simpleNode = Node \<$\> leaf \<*\> leaf+-- @+--+-- An alternative base case can also be specified directly in the `arbitrary`+-- definition with the 'withBaseCase' combinator.+--+-- 'genericArbitraryRec' is a variant of 'genericArbitrary'' with no base case.+--+-- @+-- instance Arbitrary Bush where+--   arbitrary =+--     'genericArbitraryRec' (1 '%' 2 '%' 3 '%' ())+--       \`withBaseCase\` return Leaf1+-- @++module Generic.Random.Tutorial () where++import GHC.Generics+import Generic.Random
+ test/Unit.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+#if __GLASGOW_HASKELL__ < 710+{-# LANGUAGE OverlappingInstances #-}+#endif++import GHC.Generics+import Test.QuickCheck++import Generic.Random.Generic++newtype T a = W a deriving (Generic, Show)++instance (Arbitrary a, BaseCase (T a)) => Arbitrary (T a) where+  arbitrary = genericArbitrary' uniform++f :: Gen (T (T Int))+f = arbitrary++main :: IO ()+main = sample' f >>= force+  where+    force [] = return ()+    force (x : xs) = x `seq` force xs