git.iko.soy/typeable/generic-arbitrary
on master help sign in
Initial commit
commit67849c741253631f6c5d0bc79dec0ddab523203d authorVladislav Zavialov <vlad.z.4096@gmail.com> dateSun 5 Mar 2017, 22:16 (10 years ago)
7 files changed+122
.gitignore+5 CHANGELOG.md+4 LICENSE+20 Setup.hs+2 generic-arbitrary.cabal+23 src/Test/QuickCheck/Arbitrary/Generic.hs+67 stack.yaml+1
.gitignorenew file+5
@@ -0,0 +1,5 @@
1+tags
2+dist
3+.stack-work
4+.cabal-sandbox/
5+cabal.sandbox.config
CHANGELOG.mdnew file+4
@@ -0,0 +1,4 @@
1+0.1.0
2+-----
3+
4+* Public release
LICENSEnew file+20
@@ -0,0 +1,20 @@
1+Copyright (c) 2016 Typeable.io contributors
2+
3+Permission is hereby granted, free of charge, to any person obtaining
4+a copy of this software and associated documentation files (the
5+"Software"), to deal in the Software without restriction, including
6+without limitation the rights to use, copy, modify, merge, publish,
7+distribute, sublicense, and/or sell copies of the Software, and to
8+permit persons to whom the Software is furnished to do so, subject to
9+the following conditions:
10+
11+The above copyright notice and this permission notice shall be included
12+in all copies or substantial portions of the Software.
13+
14+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
generic-arbitrary.cabalnew file+23
@@ -0,0 +1,23 @@
1+name: generic-arbitrary
2+version: 0.1.0
3+synopsis: Generic implementation for QuickCheck's Arbitrary
4+description:
5+ Generic implementations of methods of the 'Arbitrary' class from the
6+ QuickCheck library. The approach taken here can lead to diverging instances
7+ for recursive types but is safe for non-recursive ones and guarantees
8+ flat distribution for constructors of sum-types.
9+
10+license: MIT
11+license-file: LICENSE
12+author: Typeable.io contributors
13+maintainer: makeit@typeable.io
14+category: Generic
15+build-type: Simple
16+extra-source-files: CHANGELOG.md
17+cabal-version: >=1.22
18+
19+library
20+ exposed-modules: Test.QuickCheck.Arbitrary.Generic
21+ build-depends: QuickCheck >= 2.8, base >=4.8 && <5
22+ hs-source-dirs: src
23+ default-language: Haskell2010
src/Test/QuickCheck/Arbitrary/Generic.hsnew file+67
@@ -0,0 +1,67 @@
1+{-# LANGUAGE UndecidableInstances, TypeOperators, DataKinds, TypeFamilies, ScopedTypeVariables#-}
2+
3+{- |
4+
5+Generic implementation of the 'arbitrary' method. Example usage:
6+
7+@
8+data Foo = Foo
9+ { _fooX :: X
10+ , _fooY :: Y
11+ } deriving (Generic)
12+
13+instance Arbitrary Foo where
14+ arbitrary = genericArbitrary
15+ shrink = genericShrink
16+@
17+
18+The generated 'arbitrary' method is equivalent to
19+
20+@Foo <$> arbitrary <*> arbitrary@.
21+
22+-}
23+
24+module Test.QuickCheck.Arbitrary.Generic
25+ ( Arbitrary(..)
26+ , genericArbitrary
27+ , genericShrink
28+ ) where
29+
30+import Control.Applicative
31+import Data.Proxy
32+import GHC.Generics as G
33+import GHC.TypeLits
34+import Test.QuickCheck as QC
35+
36+class GArbitrary a where
37+ gArbitrary :: QC.Gen (a x)
38+
39+instance GArbitrary G.U1 where
40+ gArbitrary = pure G.U1
41+
42+instance Arbitrary c => GArbitrary (G.K1 i c) where
43+ gArbitrary = G.K1 <$> arbitrary
44+
45+instance GArbitrary f => GArbitrary (G.M1 i c f) where
46+ gArbitrary = G.M1 <$> gArbitrary
47+
48+instance (GArbitrary a, GArbitrary b) => GArbitrary (a G.:*: b) where
49+ gArbitrary = liftA2 (G.:*:) gArbitrary gArbitrary
50+
51+-- | Calculates count of constructors encoded by particular ':+:'.
52+-- Internal use only.
53+type family SumLen a :: Nat where
54+ SumLen (a G.:+: b) = (SumLen a) + (SumLen b)
55+ SumLen a = 1
56+
57+instance (GArbitrary a, GArbitrary b, KnownNat (SumLen a), KnownNat (SumLen b)
58+ ) => GArbitrary (a G.:+: b) where
59+ gArbitrary = frequency
60+ [ (lfreq, G.L1 <$> gArbitrary)
61+ , (rfreq, G.R1 <$> gArbitrary) ]
62+ where
63+ lfreq = fromIntegral $ natVal (Proxy :: Proxy (SumLen a))
64+ rfreq = fromIntegral $ natVal (Proxy :: Proxy (SumLen b))
65+
66+genericArbitrary :: (Generic a, GArbitrary ga, ga ~ G.Rep a) => Gen a
67+genericArbitrary = G.to <$> gArbitrary
stack.yamlnew file+1
@@ -0,0 +1 @@
1+resolver: lts-6.30