quickcheck-classes-0.4.2: QuickCheck common typeclasses

Safe HaskellNone
LanguageHaskell2010

Test.QuickCheck.Classes

Contents

Description

This library provides lists of properties that should hold for common typeclasses. All of these take a Proxy argument that is used to nail down the type for which the typeclass dictionaries should be tested. For example, at GHCi:

>>> lawsCheck (monoidLaws (Proxy :: Proxy Ordering))
Monoid: Associative +++ OK, passed 100 tests.
Monoid: Left Identity +++ OK, passed 100 tests.
Monoid: Right Identity +++ OK, passed 100 tests.

Assuming that the Arbitrary instance for Ordering is good, we now have confidence that the Monoid instance for Ordering satisfies the monoid laws. We can check multiple typeclasses with:

>>> foldMap (lawsCheck . ($ (Proxy :: Proxy Word))) [jsonLaws,showReadLaws]
ToJSON/FromJSON: Encoding Equals Value +++ OK, passed 100 tests.
ToJSON/FromJSON: Partial Isomorphism +++ OK, passed 100 tests.
Show/Read: Partial Isomorphism +++ OK, passed 100 tests.

Synopsis

Running

lawsCheck :: Laws -> IO () Source #

A convenience function for working testing properties in GHCi. See the test suite of this library for an example of how to integrate multiple properties into larger test suite.

lawsCheckMany Source #

Arguments

:: [(String, [Laws])]

Element is type name paired with typeclass laws

-> IO () 

A convenience function for checking multiple typeclass instances of multiple types.

Properties

Ground Types

commutativeMonoidLaws :: (Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests everything from monoidProps plus the following:

Commutative
mappend a b ≡ mappend b a

eqLaws :: (Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Transitive
a == b ∧ b == c ⇒ a == c
Symmetric
a == b ⇒ b == a
Reflexive
a == a

Some of these properties involve implication. In the case that the left hand side of the implication arrow does not hold, we do not retry. Consequently, these properties only end up being useful when the data type has a small number of inhabitants.

ordLaws :: (Ord a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Antisymmetry
@a ≤ b ∧ b ≤ a ⇒ a = b
Transitivity
a ≤ b ∧ b ≤ c ⇒ a ≤ c
Totality
a ≤ b ∨ a > b

showReadLaws :: (Show a, Read a, Eq a, Arbitrary a) => Proxy a -> Laws Source #

jsonLaws :: (ToJSON a, FromJSON a, Show a, Arbitrary a, Eq a) => Proxy a -> Laws Source #

Tests the following properties:

Partial Isomorphism
decode . encode ≡ Just
Encoding Equals Value
decode . encode ≡ Just . toJSON

Note that in the second propertiy, the type of decode is ByteString -> Value, not ByteString -> a

integralLaws :: (Integral a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Quotient Remainder
(quot x y) * y + (rem x y) ≡ x
Division Modulus
(div x y) * y + (mod x y) ≡ x
Integer Roundtrip
fromInteger (toInteger x) ≡ x

jsonLaws :: (ToJSON a, FromJSON a, Show a, Arbitrary a, Eq a) => Proxy a -> Laws Source #

Tests the following properties:

Partial Isomorphism
decode . encode ≡ Just
Encoding Equals Value
decode . encode ≡ Just . toJSON

Note that in the second propertiy, the type of decode is ByteString -> Value, not ByteString -> a

monoidLaws :: (Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Associative
mappend a (mappend b c) ≡ mappend (mappend a b) c
Left Identity
mappend mempty a ≡ a
Right Identity
mappend a mempty ≡ a

ordLaws :: (Ord a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Antisymmetry
@a ≤ b ∧ b ≤ a ⇒ a = b
Transitivity
a ≤ b ∧ b ≤ c ⇒ a ≤ c
Totality
a ≤ b ∨ a > b

primLaws :: (Prim a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Test that a Prim instance obey the several laws.

semigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Associative
a <> (b <> c) ≡ (a <> b) <> c

showReadLaws :: (Show a, Read a, Eq a, Arbitrary a) => Proxy a -> Laws Source #

integralLaws :: (Integral a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Quotient Remainder
(quot x y) * y + (rem x y) ≡ x
Division Modulus
(div x y) * y + (mod x y) ≡ x
Integer Roundtrip
fromInteger (toInteger x) ≡ x

bitsLaws :: (FiniteBits a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Conjunction Idempotence
n .&. n ≡ n
Disjunction Idempotence
n .|. n ≡ n
Double Complement
complement (complement n) ≡ n
Set Bit
setBit n i ≡ n .|. bit i
Clear Bit
clearBit n i ≡ n .&. complement (bit i)
Complement Bit
complementBit n i ≡ xor n (bit i)
Clear Zero
clearBit zeroBits i ≡ zeroBits
Set Zero
setBit zeroBits i ≡ bit i
Test Zero
testBit zeroBits i ≡ False
Pop Zero
popCount zeroBits ≡ 0
Count Leading Zeros of Zero
countLeadingZeros zeroBits ≡ finiteBitSize ⊥
Count Trailing Zeros of Zero
countTrailingZeros zeroBits ≡ finiteBitSize ⊥

All of the useful instances of the Bits typeclass also have FiniteBits instances, so these property tests actually require that instance as well.

Note: This property test is only available when using base-4.7 or newer.

isListLaws :: (IsList a, Show a, Show (Item a), Arbitrary a, Arbitrary (Item a), Eq a) => Proxy a -> Laws Source #

Tests the following properties:

Partial Isomorphism
fromList . toList ≡ id
Length Preservation
fromList xs ≡ fromListN (length xs) xs

Note: This property test is only available when using base-4.7 or newer.

Higher-Kinded Types

altLaws :: (Alt f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws Source #

Tests the following alt properties:

Associativity
(a <!> b) <!> c ≡ a <!> (b <!> c)
Left Distributivity
@f <$> (a <!> b) = (f <$> a) <!> (f <$> b)

alternativeLaws :: (Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws Source #

Tests the following alternative properties:

Identity
empty <|> x ≡ x x <|> empty ≡ x
Associativity
a <|> (b <|> c) ≡ (a <|> b) <|> c)

applicativeLaws :: (Applicative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws Source #

Tests the following applicative properties:

Identity
pure id <*> v ≡ v
Composition
pure (.) <*> u <*> v <*> w ≡ u <*> (v <*> w)
Homomorphism
pure f <*> pure x ≡ pure (f x)
Interchange
u <*> pure y ≡ pure ($ y) <*> u
LiftA2 (1)
(<*>) ≡ liftA2 id

foldableLaws :: (Foldable f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws Source #

Tests the following Foldable properties:

fold
foldfoldMap id
foldMap
foldMap f ≡ foldr (mappend . f) mempty
foldr
foldr f z t ≡ appEndo (foldMap (Endo . f) t ) z
foldr'
foldr' f z0 xs = let f' k x z = k $! f x z in foldl f' id xs z0
foldl
foldl f z t ≡ appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z
foldl'
foldl' f z0 xs = let f' x k z = k $! f z x in foldr f' id xs z0
toList
toListfoldr (:) []
null
nullfoldr (const (const False)) True
length
length ≡ getSum . foldMap (const (Sum 1))

Note that this checks to ensure that foldl' and foldr' are suitably strict.

functorLaws :: (Functor f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws Source #

Tests the following functor properties:

Identity
fmap idid
Composition
fmap (f . g) ≡ fmap f . fmap g
Const
(<$) ≡ fmap const

monadLaws :: (Monad f, Applicative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws Source #

Tests the following monadic properties:

Left Identity
return a >>= k ≡ k a
Right Identity
m >>= return ≡ m
Associativity
m >>= (\x -> k x >>= h) ≡ (m >>= k) >>= h
Return
purereturn
Ap
(<*>) ≡ ap

bifunctorLaws :: (Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f) => proxy f -> Laws Source #

Tests the following Bifunctor properties:

Identity
bimap id idid
First Identity
first idid
Second Identity
second idid
Bifunctor Composition
bimap f g ≡ first f . second g

Note: This property test is only available when this package is built with base-4.9+ or transformers-0.5+.

Types

data Laws Source #

A set of laws associated with a typeclass.

Constructors

Laws 

Fields