Skip to content

Commit 73d0937

Browse files
committed
Merge pull request #8 from jdegoes/master
add instances for either, maybe, and tuple, and some helper functions
2 parents 324b2f6 + 171e506 commit 73d0937

File tree

6 files changed

+151
-20
lines changed

6 files changed

+151
-20
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,36 @@
3434

3535
instance arbBoolean :: Arbitrary Boolean
3636

37+
instance arbEither :: (Arbitrary a, Arbitrary b) => Arbitrary (Either a b)
38+
3739
instance arbFunction :: (CoArbitrary a, Arbitrary b) => Arbitrary (a -> b)
3840

41+
instance arbMaybe :: (Arbitrary a) => Arbitrary (Maybe a)
42+
3943
instance arbNumber :: Arbitrary Number
4044

4145
instance arbString :: Arbitrary String
4246

47+
instance arbTuple :: (Arbitrary a, Arbitrary b) => Arbitrary (Tuple a b)
48+
4349
instance coarbAlphaNumString :: CoArbitrary AlphaNumString
4450

4551
instance coarbArray :: (CoArbitrary a) => CoArbitrary [a]
4652

4753
instance coarbBoolean :: CoArbitrary Boolean
4854

55+
instance coarbEither :: (CoArbitrary a, CoArbitrary b) => CoArbitrary (Either a b)
56+
4957
instance coarbFunction :: (Arbitrary a, CoArbitrary b) => CoArbitrary (a -> b)
5058

59+
instance coarbMaybe :: (CoArbitrary a) => CoArbitrary (Maybe a)
60+
5161
instance coarbNumber :: CoArbitrary Number
5262

5363
instance coarbString :: CoArbitrary String
5464

65+
instance coarbTuple :: (CoArbitrary a, CoArbitrary b) => CoArbitrary (Tuple a b)
66+
5567
instance showResult :: Show Result
5668

5769
instance testableBoolean :: Testable Boolean

bower.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
"package.json"
1515
],
1616
"dependencies": {
17-
"purescript-random": "*",
18-
"purescript-exceptions": "0.2.0",
19-
"purescript-arrays": "*",
20-
"purescript-strings": "*",
21-
"purescript-math": "*"
17+
"purescript-random": "*",
18+
"purescript-exceptions": "*",
19+
"purescript-arrays": "*",
20+
"purescript-strings": "*",
21+
"purescript-math": "*",
22+
"purescript-tuples": "*",
23+
"purescript-either": "*",
24+
"purescript-maybe": "*",
25+
"purescript-foldable-traversable": "*"
2226
}
2327
}

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"name": "purescript-quickcheck",
3-
"version": "0.0.2",
43
"license": "MIT",
54
"repository": "[email protected]:purescript-contrib/purescript-quickcheck.git",
65

src/Test/QuickCheck.purs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import Control.Monad.Eff
66
import Control.Monad.Eff.Random
77
import Control.Monad.Eff.Exception
88
import Data.Array
9+
import Data.Tuple
10+
import Data.Maybe
11+
import Data.Either
912
import Math
1013

1114
import qualified Data.String as S
@@ -65,16 +68,37 @@ instance arbAlphaNumString :: Arbitrary AlphaNumString where
6568
instance coarbAlphaNumString :: CoArbitrary AlphaNumString where
6669
coarbitrary (AlphaNumString s) = coarbitrary s
6770

71+
instance arbTuple :: (Arbitrary a, Arbitrary b) => Arbitrary (Tuple a b) where
72+
arbitrary = Tuple <$> arbitrary <*> arbitrary
73+
74+
instance coarbTuple :: (CoArbitrary a, CoArbitrary b) => CoArbitrary (Tuple a b) where
75+
coarbitrary (Tuple a b) = coarbitrary a >>> coarbitrary b
76+
77+
instance arbEither :: (Arbitrary a, Arbitrary b) => Arbitrary (Either a b) where
78+
arbitrary = do
79+
b <- arbitrary
80+
if b then Left <$> arbitrary else Right <$> arbitrary
81+
82+
instance coarbEither :: (CoArbitrary a, CoArbitrary b) => CoArbitrary (Either a b) where
83+
coarbitrary (Left a) = coarbitrary a
84+
coarbitrary (Right b) = coarbitrary b
85+
86+
instance arbMaybe :: (Arbitrary a) => Arbitrary (Maybe a) where
87+
arbitrary = do
88+
b <- arbitrary
89+
if b then pure Nothing else Just <$> arbitrary
90+
91+
instance coarbMaybe :: (CoArbitrary a) => CoArbitrary (Maybe a) where
92+
coarbitrary Nothing = perturbGen 1
93+
coarbitrary (Just a) = coarbitrary a
94+
6895
instance arbFunction :: (CoArbitrary a, Arbitrary b) => Arbitrary (a -> b) where
6996
arbitrary = repeatable (\a -> coarbitrary a arbitrary)
7097

7198
instance coarbFunction :: (Arbitrary a, CoArbitrary b) => CoArbitrary (a -> b) where
7299
coarbitrary f gen = do
73100
xs <- arbitrary
74101
coarbitrary (map f xs) gen
75-
where
76-
map _ [] = []
77-
map f (x : xs) = f x : map f xs
78102

79103
instance arbArray :: (Arbitrary a) => Arbitrary [a] where
80104
arbitrary = do

src/Test/QuickCheck/LCG.purs

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,36 @@ module Test.QuickCheck.LCG
66
Size(),
77
LCG(),
88
repeatable,
9-
sized,
109
stateful,
10+
variant,
11+
sized,
1112
resize,
13+
choose,
14+
chooseInt,
15+
oneOf,
16+
frequency,
17+
listOf,
18+
listOf1,
19+
vectorOf,
20+
elements,
1221
runGen,
1322
evalGen,
1423
perturbGen,
15-
uniform
24+
uniform,
25+
showSample,
26+
showSample'
1627
) where
1728

1829
import Control.Monad.Eff
1930
import Control.Monad.Eff.Random
31+
import Debug.Trace
32+
import Data.Maybe
33+
import Data.Tuple
34+
import Data.Foldable
35+
import Data.Traversable
36+
import Data.Monoid.Sum
37+
import qualified Data.Array as A
38+
import qualified Math as M
2039

2140
type LCG = Number
2241
type Size = Number
@@ -30,20 +49,76 @@ data Gen a = Gen (GenState -> GenOut a)
3049
repeatable :: forall a b. (a -> Gen b) -> Gen (a -> b)
3150
repeatable f = Gen $ \s -> { value: \a -> (runGen (f a) s).value, state: s }
3251

33-
sized :: forall a. (Number -> Gen a) -> Gen a
34-
sized f = stateful (\s -> f s.size)
35-
3652
stateful :: forall a. (GenState -> Gen a) -> Gen a
3753
stateful f = Gen (\s -> runGen (f s) s)
3854

39-
resize :: forall a. Number -> Gen a -> Gen a
40-
resize sz g = Gen (\s -> runGen g s { size = sz })
55+
variant :: forall a. LCG -> Gen a -> Gen a
56+
variant n g = Gen $ \s -> runGen g s { newSeed = n }
57+
58+
sized :: forall a. (Size -> Gen a) -> Gen a
59+
sized f = stateful (\s -> f s.size)
60+
61+
resize :: forall a. Size -> Gen a -> Gen a
62+
resize sz g = Gen $ \s -> runGen g s { size = sz }
63+
64+
choose :: Number -> Number -> Gen Number
65+
choose a b = (*) (max - min) >>> (+) min <$> uniform where
66+
min = M.min a b
67+
max = M.max a b
68+
69+
chooseInt :: Number -> Number -> Gen Number
70+
chooseInt a b = M.floor <$> choose (M.ceil a) (M.floor b + 0.999999999)
71+
72+
oneOf :: forall a. Gen a -> [Gen a] -> Gen a
73+
oneOf x xs = do
74+
n <- chooseInt 0 (A.length xs)
75+
if n == 0 then x else fromMaybe x (xs A.!! (n - 1))
76+
77+
frequency :: forall a. Tuple Number (Gen a) -> [Tuple Number (Gen a)] -> Gen a
78+
frequency x xs = let
79+
xxs = x : xs
80+
total = runSum $ fold (((Sum <<< fst) <$> xxs) :: [Sum])
81+
pick n d [] = d
82+
pick n d ((Tuple k x) : xs) = if n <= k then x else pick (n - k) d xs
83+
in do
84+
n <- chooseInt 1 total
85+
pick n (snd x) xxs
86+
87+
listOf :: forall a. Gen a -> Gen [a]
88+
listOf g = sized $ \n ->
89+
do k <- chooseInt 0 n
90+
vectorOf k g
91+
92+
listOf1 :: forall a. Gen a -> Gen (Tuple a [a])
93+
listOf1 g = sized $ \n ->
94+
do k <- chooseInt 0 n
95+
x <- g
96+
xs <- vectorOf (k - 1) g
97+
return $ Tuple x xs
98+
99+
vectorOf :: forall a. Number -> Gen a -> Gen [a]
100+
vectorOf k g = sequence $ const g <$> (A.range 1 k)
101+
102+
elements :: forall a. a -> [a] -> Gen a
103+
elements x xs = do
104+
n <- chooseInt 0 (A.length xs)
105+
pure if n == 0 then x else fromMaybe x (xs A.!! (n - 1))
41106

42107
runGen :: forall a. Gen a -> GenState -> GenOut a
43108
runGen (Gen f) = f
44109

45110
evalGen :: forall a. Gen a -> GenState -> a
46111
evalGen gen st = (runGen gen st).value
112+
113+
sample :: forall r a. Size -> Gen a -> [a]
114+
sample sz g = evalGen (vectorOf sz g) { newSeed: 0, size: sz }
115+
116+
showSample' :: forall r a. (Show a) => Size -> Gen a -> Eff (trace :: Trace | r) Unit
117+
showSample' n g = print $ sample n g
118+
119+
showSample :: forall r a. (Show a) => Gen a -> Eff (trace :: Trace | r) Unit
120+
showSample = showSample' 10
121+
47122
--
48123
-- Magic Numbers
49124
--
@@ -96,5 +171,4 @@ instance bindGen :: Bind Gen where
96171
(>>=) (Gen f) g = Gen $ \s -> case f s of
97172
{ value = value, state = state } -> runGen (g value) state
98173

99-
instance monadGen :: Monad Gen
100-
174+
instance monadGen :: Monad Gen

src/Test/QuickCheck/README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,39 @@
3030

3131
### Values
3232

33+
choose :: Number -> Number -> Gen Number
34+
35+
chooseInt :: Number -> Number -> Gen Number
36+
37+
elements :: forall a. a -> [a] -> Gen a
38+
3339
evalGen :: forall a. Gen a -> GenState -> a
3440

41+
frequency :: forall a. Tuple Number (Gen a) -> [Tuple Number (Gen a)] -> Gen a
42+
43+
listOf :: forall a. Gen a -> Gen [a]
44+
45+
listOf1 :: forall a. Gen a -> Gen (Tuple a [a])
46+
47+
oneOf :: forall a. Gen a -> [Gen a] -> Gen a
48+
3549
perturbGen :: forall a. Number -> Gen a -> Gen a
3650

3751
repeatable :: forall a b. (a -> Gen b) -> Gen (a -> b)
3852

39-
resize :: forall a. Number -> Gen a -> Gen a
53+
resize :: forall a. Size -> Gen a -> Gen a
4054

4155
runGen :: forall a. Gen a -> GenState -> GenOut a
4256

43-
sized :: forall a. (Number -> Gen a) -> Gen a
57+
sized :: forall a. (Size -> Gen a) -> Gen a
4458

4559
stateful :: forall a. (GenState -> Gen a) -> Gen a
4660

4761
uniform :: Gen Number
4862

63+
variant :: forall a. LCG -> Gen a -> Gen a
64+
65+
vectorOf :: forall a. Number -> Gen a -> Gen [a]
66+
4967

5068

0 commit comments

Comments
 (0)