Skip to content

Commit 14286c6

Browse files
committed
Updates for 0.7
1 parent f70074f commit 14286c6

File tree

7 files changed

+93
-80
lines changed

7 files changed

+93
-80
lines changed

src/Test/QuickCheck.purs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
-- | ```
1818
module Test.QuickCheck where
1919

20+
import Prelude
21+
2022
import Console (CONSOLE(), log)
21-
import Control.Monad (replicateM)
2223
import Control.Monad.Eff (Eff())
2324
import Control.Monad.Eff.Exception (EXCEPTION(), throwException, error)
2425
import Control.Monad.Eff.Random (RANDOM(), random)
25-
import Data.Int (Int(), fromNumber, toNumber)
26+
import Data.Int (fromNumber, toNumber)
27+
import Data.List (List(..), replicateM)
2628
import Test.QuickCheck.Arbitrary
2729
import Test.QuickCheck.Gen
2830
import Test.QuickCheck.LCG
@@ -35,7 +37,7 @@ type QC a = forall eff. Eff (console :: CONSOLE, random :: RANDOM, err :: EXCEPT
3537
-- | This function generates a new random seed, runs 100 tests and
3638
-- | prints the test results to the console.
3739
quickCheck :: forall prop. (Testable prop) => prop -> QC Unit
38-
quickCheck prop = quickCheck' (fromNumber 100) prop
40+
quickCheck prop = quickCheck' 100 prop
3941

4042
-- | A variant of the `quickCheck` function which accepts an extra parameter
4143
-- | representing the number of tests which should be run.
@@ -49,22 +51,22 @@ quickCheck' n prop = do
4951

5052
where
5153

52-
throwOnFirstFailure :: Int -> [Result] -> QC Unit
53-
throwOnFirstFailure _ [] = return unit
54-
throwOnFirstFailure n (Failed msg : _) = throwException $ error $ "Test " ++ show (toNumber n) ++ " failed: \n" ++ msg
55-
throwOnFirstFailure n (_ : rest) = throwOnFirstFailure (n + one) rest
54+
throwOnFirstFailure :: Int -> List Result -> QC Unit
55+
throwOnFirstFailure _ Nil = return unit
56+
throwOnFirstFailure n (Cons (Failed msg) _) = throwException $ error $ "Test " ++ show (toNumber n) ++ " failed: \n" ++ msg
57+
throwOnFirstFailure n (Cons _ rest) = throwOnFirstFailure (n + one) rest
5658

57-
countSuccesses :: [Result] -> Int
58-
countSuccesses [] = zero
59-
countSuccesses (Success : rest) = one + countSuccesses rest
60-
countSuccesses (_ : rest) = countSuccesses rest
59+
countSuccesses :: List Result -> Int
60+
countSuccesses Nil = zero
61+
countSuccesses (Cons Success rest) = one + countSuccesses rest
62+
countSuccesses (Cons _ rest) = countSuccesses rest
6163

6264
-- | Test a property, returning all test results as an array.
6365
-- |
6466
-- | The first argument is the _random seed_ to be passed to the random generator.
6567
-- | The second argument is the number of tests to run.
66-
quickCheckPure :: forall prop. (Testable prop) => Int -> Int -> prop -> [Result]
67-
quickCheckPure s n prop = evalGen (replicateM n (test prop)) { newSeed: s, size: fromNumber 10 }
68+
quickCheckPure :: forall prop. (Testable prop) => Int -> Int -> prop -> List Result
69+
quickCheckPure s n prop = evalGen (replicateM n (test prop)) { newSeed: s, size: 10 }
6870

6971
-- | The `Testable` class represents _testable properties_.
7072
-- |

src/Test/QuickCheck/Arbitrary.purs

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
module Test.QuickCheck.Arbitrary where
22

3-
import Data.Array (map)
4-
import Data.Char (Char(), toCharCode, fromCharCode)
3+
import Prelude
4+
5+
import Data.Array ((:))
6+
import Data.Char (toCharCode, fromCharCode)
57
import Data.Either (Either(..))
68
import Data.Maybe (Maybe(..))
79
import Data.String (charCodeAt, fromCharArray, split)
810
import Data.Tuple (Tuple(..))
9-
import Data.Int (Int(), fromNumber, toNumber)
11+
import Data.Int (fromNumber, toNumber)
12+
import Data.Foldable (foldl)
1013
import Test.QuickCheck.Gen
1114

1215
-- | The `Arbitrary` class represents those types whose values can be
@@ -32,11 +35,11 @@ class Coarbitrary t where
3235
instance arbBoolean :: Arbitrary Boolean where
3336
arbitrary = do
3437
n <- uniform
35-
return $ (n * 2) < 1
38+
return $ (n * 2.0) < 1.0
3639

3740
instance coarbBoolean :: Coarbitrary Boolean where
38-
coarbitrary true = perturbGen 1
39-
coarbitrary false = perturbGen 2
41+
coarbitrary true = perturbGen 1.0
42+
coarbitrary false = perturbGen 2.0
4043

4144
instance arbNumber :: Arbitrary Number where
4245
arbitrary = uniform
@@ -45,7 +48,7 @@ instance coarbNumber :: Coarbitrary Number where
4548
coarbitrary = perturbGen
4649

4750
instance arbInt :: Arbitrary Int where
48-
arbitrary = chooseInt (fromNumber (-1000000)) (fromNumber 1000000)
51+
arbitrary = chooseInt (-1000000) 1000000
4952

5053
instance coarbInt :: Coarbitrary Int where
5154
coarbitrary = perturbGen <<< toNumber
@@ -57,7 +60,7 @@ instance coarbString :: Coarbitrary String where
5760
coarbitrary s = coarbitrary $ (charCodeAt zero <$> split "" s)
5861

5962
instance arbChar :: Arbitrary Char where
60-
arbitrary = fromCharCode <<< fromNumber <<< (* 65535) <$> uniform
63+
arbitrary = fromCharCode <$> chooseInt 0 65536
6164

6265
instance coarbChar :: Coarbitrary Char where
6366
coarbitrary c = coarbitrary $ toCharCode c
@@ -66,40 +69,34 @@ instance arbUnit :: Arbitrary Unit where
6669
arbitrary = return unit
6770

6871
instance coarbUnit :: Coarbitrary Unit where
69-
coarbitrary _ = perturbGen 1
72+
coarbitrary _ = perturbGen 1.0
7073

7174
instance arbOrdering :: Arbitrary Ordering where
72-
arbitrary = do
73-
n <- chooseInt (fromNumber 1) (fromNumber 3)
74-
return $ case toNumber n of
75-
1 -> LT
76-
2 -> EQ
77-
3 -> GT
75+
arbitrary = oneOf (pure LT) [pure EQ, pure GT]
7876

7977
instance coarbOrdering :: Coarbitrary Ordering where
80-
coarbitrary LT = perturbGen 1
81-
coarbitrary EQ = perturbGen 2
82-
coarbitrary GT = perturbGen 3
78+
coarbitrary LT = perturbGen 1.0
79+
coarbitrary EQ = perturbGen 2.0
80+
coarbitrary GT = perturbGen 3.0
8381

84-
instance arbArray :: (Arbitrary a) => Arbitrary [a] where
82+
instance arbArray :: (Arbitrary a) => Arbitrary (Array a) where
8583
arbitrary = do
8684
b <- arbitrary
8785
if b then return [] else do
8886
a <- arbitrary
8987
as <- arbitrary
9088
return (a : as)
9189

92-
instance coarbArray :: (Coarbitrary a) => Coarbitrary [a] where
93-
coarbitrary [] = id
94-
coarbitrary (x : xs) = coarbitrary xs <<< coarbitrary x
90+
instance coarbArray :: (Coarbitrary a) => Coarbitrary (Array a) where
91+
coarbitrary = foldl (\f x -> f <<< coarbitrary x) id
9592

9693
instance arbFunction :: (Coarbitrary a, Arbitrary b) => Arbitrary (a -> b) where
9794
arbitrary = repeatable (\a -> coarbitrary a arbitrary)
9895

9996
instance coarbFunction :: (Arbitrary a, Coarbitrary b) => Coarbitrary (a -> b) where
10097
coarbitrary f gen = do
10198
xs <- arbitrary
102-
coarbitrary (map f xs) gen
99+
coarbitrary (map f (xs :: Array a)) gen
103100

104101
instance arbTuple :: (Arbitrary a, Arbitrary b) => Arbitrary (Tuple a b) where
105102
arbitrary = Tuple <$> arbitrary <*> arbitrary
@@ -113,7 +110,7 @@ instance arbMaybe :: (Arbitrary a) => Arbitrary (Maybe a) where
113110
if b then pure Nothing else Just <$> arbitrary
114111

115112
instance coarbMaybe :: (Coarbitrary a) => Coarbitrary (Maybe a) where
116-
coarbitrary Nothing = perturbGen 1
113+
coarbitrary Nothing = perturbGen 1.0
117114
coarbitrary (Just a) = coarbitrary a
118115

119116
instance arbEither :: (Arbitrary a, Arbitrary b) => Arbitrary (Either a b) where
Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
module Test.QuickCheck.Data.AlphaNumString where
22

3+
import Prelude
4+
35
import Data.Int (fromNumber, toNumber)
4-
import Data.String (fromCharArray, length)
6+
import Data.String (fromCharArray, toCharArray, length)
57
import Data.String.Unsafe (charAt)
68
import Math (round)
9+
import Test.QuickCheck.Gen
710
import Test.QuickCheck.Arbitrary
811

912
-- | A newtype for `String` whose `Arbitrary` instance generated random
1013
-- | alphanumeric strings.
1114
newtype AlphaNumString = AlphaNumString String
1215

16+
runAlphaNumString :: AlphaNumString -> String
1317
runAlphaNumString (AlphaNumString s) = s
1418

1519
instance arbAlphaNumString :: Arbitrary AlphaNumString where
16-
arbitrary = do
17-
arrNum <- arbitrary
18-
return $ AlphaNumString <<< fromCharArray $ lookup <$> arrNum
20+
arbitrary = AlphaNumString <<< fromCharArray <$> arrayOf anyChar
1921
where
20-
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
21-
lookup x = let index = fromNumber $ x * (toNumber (length chars) - 1)
22-
in charAt index chars
23-
22+
rest :: Array Char
23+
rest = toCharArray "bcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
24+
25+
anyChar :: Gen Char
26+
anyChar = oneOf (pure 'a') (map pure rest)
2427

2528
instance coarbAlphaNumString :: Coarbitrary AlphaNumString where
2629
coarbitrary (AlphaNumString s) = coarbitrary s

src/Test/QuickCheck/Data/ApproxNumber.purs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module Test.QuickCheck.Data.ApproxNumber where
22

3+
import Prelude
4+
35
import Test.QuickCheck.Arbitrary
46

57
-- | A newtype for `Number` whose `Eq` instance uses an epsilon value to allow
@@ -19,24 +21,23 @@ instance coarbitraryApproxNumber :: Coarbitrary ApproxNumber where
1921
coarbitrary (ApproxNumber n) = coarbitrary n
2022

2123
instance eqApproxNumber :: Eq ApproxNumber where
22-
(==) (ApproxNumber x) (ApproxNumber y) = x =~= y
23-
(/=) (ApproxNumber x) (ApproxNumber y) = not (x =~= y)
24+
eq (ApproxNumber x) (ApproxNumber y) = x =~= y
2425

2526
instance ordApproxNumber :: Ord ApproxNumber where
2627
compare (ApproxNumber x) (ApproxNumber y) = compare x y
2728

2829
instance semiringApproxNumber :: Semiring ApproxNumber where
29-
(+) (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x + y)
30+
add (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x + y)
3031
zero = ApproxNumber zero
31-
(*) (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x * y)
32+
mul (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x * y)
3233
one = ApproxNumber one
3334

3435
instance moduloSemiringApproxNumber :: ModuloSemiring ApproxNumber where
35-
(/) (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x / y)
36+
div (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x / y)
3637
mod (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x `mod` y)
3738

3839
instance ringApproxNumber :: Ring ApproxNumber where
39-
(-) (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x - y)
40+
sub (ApproxNumber x) (ApproxNumber y) = ApproxNumber (x - y)
4041

4142
instance divisionRingApproxNumber :: DivisionRing ApproxNumber
4243
instance numApproxNumber :: Num ApproxNumber

src/Test/QuickCheck/Gen.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* global exports */
2+
"use strict";
3+
4+
// module Test.QuickCheck.Gen
5+
6+
exports.float32ToInt32 = function(n) {
7+
var arr = new ArrayBuffer(4);
8+
var fv = new Float32Array(arr);
9+
var iv = new Int32Array(arr);
10+
fv[0] = n;
11+
return iv[0];
12+
};

src/Test/QuickCheck/Gen.purs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,18 @@ module Test.QuickCheck.Gen
2626
, showSample'
2727
) where
2828

29+
import Prelude
30+
2931
import Console (CONSOLE(), print)
3032
import Control.Monad.Eff (Eff())
3133
import Data.Array ((!!), length, range)
3234
import Data.Foldable (fold)
33-
import Data.Int (Int(), fromNumber, toNumber)
35+
import Data.Int (fromNumber, toNumber)
3436
import Data.Maybe (fromMaybe)
3537
import Data.Monoid.Additive (Additive(..), runAdditive)
3638
import Data.Traversable (sequence)
3739
import Data.Tuple (Tuple(..), fst, snd)
40+
import Data.List (List(..))
3841
import Test.QuickCheck.LCG
3942
import qualified Math as M
4043

@@ -86,44 +89,44 @@ chooseInt a b = fromNumber <$> choose (toNumber a) (toNumber b + 0.999999999)
8689

8790
-- | Create a random generator which selects and executes a random generator from
8891
-- | a non-empty collection of random generators with uniform probability.
89-
oneOf :: forall a. Gen a -> [Gen a] -> Gen a
92+
oneOf :: forall a. Gen a -> Array (Gen a) -> Gen a
9093
oneOf x xs = do
9194
n <- chooseInt zero (length xs)
9295
if n < one then x else fromMaybe x (xs !! (n - one))
9396

9497
-- | Create a random generator which selects and executes a random generator from
9598
-- | a non-empty, weighted collection of random generators.
96-
frequency :: forall a. Tuple Number (Gen a) -> [Tuple Number (Gen a)] -> Gen a
99+
frequency :: forall a. Tuple Number (Gen a) -> List (Tuple Number (Gen a)) -> Gen a
97100
frequency x xs = let
98-
xxs = x : xs
99-
total = runAdditive $ fold (((Additive <<< fst) <$> xxs) :: [Additive Number])
100-
pick n d [] = d
101-
pick n d ((Tuple k x) : xs) = if n <= k then x else pick (n - k) d xs
101+
xxs = Cons x xs
102+
total = runAdditive $ fold (map (Additive <<< fst) xxs :: List (Additive Number))
103+
pick n d Nil = d
104+
pick n d (Cons (Tuple k x) xs) = if n <= k then x else pick (n - k) d xs
102105
in do
103-
n <- choose 0 total
106+
n <- choose zero total
104107
pick n (snd x) xxs
105108

106109
-- | Create a random generator which generates an array of random values.
107-
arrayOf :: forall a. Gen a -> Gen [a]
110+
arrayOf :: forall a. Gen a -> Gen (Array a)
108111
arrayOf g = sized $ \n ->
109112
do k <- chooseInt zero n
110113
vectorOf k g
111114

112115
-- | Create a random generator which generates a non-empty array of random values.
113-
arrayOf1 :: forall a. Gen a -> Gen (Tuple a [a])
116+
arrayOf1 :: forall a. Gen a -> Gen (Tuple a (Array a))
114117
arrayOf1 g = sized $ \n ->
115118
do k <- chooseInt zero n
116119
x <- g
117120
xs <- vectorOf (k - one) g
118121
return $ Tuple x xs
119122

120123
-- | Create a random generator which generates a vector of random values of a specified size.
121-
vectorOf :: forall a. Int -> Gen a -> Gen [a]
124+
vectorOf :: forall a. Int -> Gen a -> Gen (Array a)
122125
vectorOf k g = sequence $ const g <$> range one k
123126

124127
-- | Create a random generator which selects a value from a non-empty collection with
125128
-- | uniform probability.
126-
elements :: forall a. a -> [a] -> Gen a
129+
elements :: forall a. a -> Array a -> Gen a
127130
elements x xs = do
128131
n <- chooseInt zero (length xs)
129132
pure if n == zero then x else fromMaybe x (xs !! (n - one))
@@ -137,7 +140,7 @@ evalGen :: forall a. Gen a -> GenState -> a
137140
evalGen gen st = (runGen gen st).value
138141

139142
-- | Sample a random generator
140-
sample :: forall r a. Size -> Gen a -> [a]
143+
sample :: forall r a. Size -> Gen a -> Array a
141144
sample sz g = evalGen (vectorOf sz g) { newSeed: zero, size: sz }
142145

143146
-- | Print a random sample to the console
@@ -146,7 +149,7 @@ showSample' n g = print $ sample n g
146149

147150
-- | Print a random sample of 10 values to the console
148151
showSample :: forall r a. (Show a) => Gen a -> Eff (console :: CONSOLE | r) Unit
149-
showSample = showSample' (fromNumber 10)
152+
showSample = showSample' 10
150153

151154
-- | A random generator which simply outputs the current seed
152155
lcgStep :: Gen Int
@@ -157,25 +160,18 @@ lcgStep = Gen f where
157160
uniform :: Gen Number
158161
uniform = (\n -> toNumber n / toNumber lcgN) <$> lcgStep
159162

160-
foreign import float32ToInt32
161-
"function float32ToInt32(n) {\
162-
\ var arr = new ArrayBuffer(4);\
163-
\ var fv = new Float32Array(arr);\
164-
\ var iv = new Int32Array(arr);\
165-
\ fv[0] = n;\
166-
\ return iv[0];\
167-
\}" :: Number -> Int
163+
foreign import float32ToInt32 :: Number -> Int
168164

169165
-- | Perturb a random generator by modifying the current seed
170166
perturbGen :: forall a. Number -> Gen a -> Gen a
171167
perturbGen n (Gen f) = Gen $ \s -> f (s { newSeed = lcgNext (float32ToInt32 n) + s.newSeed })
172168

173169
instance functorGen :: Functor Gen where
174-
(<$>) f (Gen g) = Gen $ \s -> case g s of
170+
map f (Gen g) = Gen $ \s -> case g s of
175171
{ value = value, state = state } -> { value: f value, state: state }
176172

177173
instance applyGen :: Apply Gen where
178-
(<*>) (Gen f) (Gen x) = Gen $ \s ->
174+
apply (Gen f) (Gen x) = Gen $ \s ->
179175
case f s of
180176
{ value = f', state = s' } -> case x s' of
181177
{ value = x', state = s'' } -> { value: f' x', state: s'' }
@@ -184,7 +180,7 @@ instance applicativeGen :: Applicative Gen where
184180
pure a = Gen (\s -> { value: a, state: s })
185181

186182
instance bindGen :: Bind Gen where
187-
(>>=) (Gen f) g = Gen $ \s -> case f s of
183+
bind (Gen f) g = Gen $ \s -> case f s of
188184
{ value = value, state = state } -> runGen (g value) state
189185

190186
instance monadGen :: Monad Gen

0 commit comments

Comments
 (0)