quickcheck-classes-0.6.1.0: QuickCheck common typeclasses

Safe HaskellNone
LanguageHaskell2010

Test.QuickCheck.Classes

Contents

Description

This library provides sets of properties that should hold for common typeclasses.

Note: on GHC < 8.5, this library uses the higher-kinded typeclasses (Show1, Eq1, Ord1, etc.), but on GHC >= 8.5, it uses `-XQuantifiedConstraints` to express these constraints more cleanly.

Synopsis

Running

lawsCheck :: Laws -> IO () Source #

A convenience function for testing properties in GHCi. 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.

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. Consider the following Haskell source file:

import Data.Proxy (Proxy(..))
import Data.Map (Map)
import Data.Set (Set)

-- A Proxy for Set Int.
setInt :: Proxy (Set Int)
setInt = Proxy

-- A Proxy for Map Int Int.
mapInt :: Proxy (Map Int Int)
mapInt = Proxy

myLaws :: Proxy a -> [Laws]
myLaws p = [eqLaws p, monoidLaws p]

namedTests :: [(String, [Laws])]
namedTests =
  [ ("Set Int", myLaws setInt)
  , ("Map Int Int", myLaws mapInt)
  ]

Now, in GHCi:

>>> lawsCheckMany namedTests
Testing properties for common typeclasses
-------------
-- Set Int --
-------------

Eq: Transitive +++ OK, passed 100 tests.
Eq: Symmetric +++ OK, passed 100 tests.
Eq: Reflexive +++ OK, passed 100 tests.
Monoid: Associative +++ OK, passed 100 tests.
Monoid: Left Identity +++ OK, passed 100 tests.
Monoid: Right Identity +++ OK, passed 100 tests.
Monoid: Concatenation +++ OK, passed 100 tests.

-----------------
-- Map Int Int --
-----------------

Eq: Transitive +++ OK, passed 100 tests.
Eq: Symmetric +++ OK, passed 100 tests.
Eq: Reflexive +++ OK, passed 100 tests.
Monoid: Associative +++ OK, passed 100 tests.
Monoid: Left Identity +++ OK, passed 100 tests.
Monoid: Right Identity +++ OK, passed 100 tests.
Monoid: Concatenation +++ OK, passed 100 tests.

In the case of a failing test, the program terminates with exit code 1.

lawsCheckOne :: Proxy a -> [Proxy a -> Laws] -> IO () Source #

A convenience function that allows one to check many typeclass instances of the same type.

>>> specialisedLawsCheckMany (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.

Properties

Ground types

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.

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.

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

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.

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 property, 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
Concatenation
mconcat as ≡ foldr mappend mempty as

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

Tests the following properties:

Commutative
mappend a b ≡ mappend b a

Note that this does not test associativity or identity. Make sure to use monoidLaws in addition to this set of laws.

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

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

Tests the following properties:

Succ Pred Identity
succ (pred x) ≡ x
Pred Succ Identity
pred (succ x) ≡ x

This only works for Enum types that are not bounded, meaning that succ and pred must be total. This means that these property tests work correctly for types like Integer but not for Int.

Sadly, there is not a good way to test fromEnum and toEnum, since many types that have reasonable implementations for succ and pred have more inhabitants than Int does.

boundedEnumLaws :: (Enum a, Bounded a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the same properties as enumLaws except that it requires the type to have a Bounded instance. These tests avoid taking the successor of the maximum element or the predecessor of the minimal element.

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
Concatenation
sconcat as ≡ foldr1 (<>) as
Times
stimes n a ≡ foldr1 (<>) (replicate n a)

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

Tests the following properties:

Commutative
a <> b ≡ b <> a

Note that this does not test associativity. Make sure to use semigroupLaws in addition to this set of laws.

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

Tests the following properties:

Exponential
stimes n (a <> b) ≡ stimes n a <> stimes n b

Note that this does not test associativity. Make sure to use semigroupLaws in addition to this set of laws.

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

Tests the following properties:

Idempotent
a <> a ≡ a

Note that this does not test associativity. Make sure to use semigroupLaws in addition to this set of laws. In literature, this class of semigroup is known as a band.

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

Tests the following properties:

Rectangular Band
a <> b <> a ≡ a

Note that this does not test associativity. Make sure to use semigroupLaws in addition to this set of laws.

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

Tests the following properties:

Additive Commutativity
a + b ≡ b + a
Additive Left Identity
0 + a ≡ a
Additive Right Identity
a + 0 ≡ a
Multiplicative Associativity
a * (b * c) ≡ (a * b) * c
Multiplicative Left Identity
1 * a ≡ a
Multiplicative Right Identity
a * 1 ≡ a
Multiplication Left Distributes Over Addition
a * (b + c) ≡ (a * b) + (a * c)
Multiplication Right Distributes Over Addition
(a + b) * c ≡ (a * c) + (b * c)
Multiplicative Left Annihilation
0 * a ≡ 0
Multiplicative Right Annihilation
a * 0 ≡ 0

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

Tests the following properties:

Additive Inverse
negate a + a ≡ 0

Note that this does not test any of the laws tested by semiringLaws.

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

Tests the following properties:

Show
show a ≡ showsPrec 0 a ""
Equivariance: showsPrec
showsPrec p a r ++ s ≡ showsPrec p a (r ++ s)
Equivariance: showList
showList as r ++ s ≡ showList as (r ++ s)

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

Tests the following properties:

Partial Isomorphism: show / read
readMaybe (show a) ≡ Just a
Partial Isomorphism: show / read with initial space
readMaybe (" " ++ show a) ≡ Just a
Partial Isomorphism: showsPrec / readsPrec
(a,"") `elem` readsPrec p (showsPrec p a "")
Partial Isomorphism: showList / readList
(as,"") `elem` readList (showList as "")
Partial Isomorphism: showListWith shows / readListDefault
(as,"") `elem` readListDefault (showListWith shows as "")

Note: When using base-4.5 or older, a shim implementation of readMaybe is used.

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

Tests the following alternative properties:

Set-Get
(pokeElemOff ptr ix a >> peekElemOff ptr ix') ≡ pure a
Get-Set
(peekElemOff ptr ix >> pokeElemOff ptr ix a) ≡ pure a

genericLaws :: (Generic a, Eq a, Arbitrary a, Show a, Show (Rep a ()), Arbitrary (Rep a ()), Eq (Rep a ())) => Proxy a -> Laws Source #

Tests the following properties:

From-To Inverse
from . toid
To-From Inverse
to . fromid

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

Note: from and to don't actually care about the type variable x in Rep a x, so here we instantiate it to '()' by default. If you would like to instantiate x as something else, please file a bug report.

generic1Laws :: (Generic1 f, Eq1 f, Arbitrary1 f, Show1 f, Eq1 (Rep1 f), Show1 (Rep1 f), Arbitrary1 (Rep1 f)) => proxy f -> Laws Source #

Tests the following properties:

From-To Inverse
from1 . to1id
To-From Inverse
to1 . from1id

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

Unary type constructors

alternativeLaws :: (Alternative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following alternative properties:

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

altLaws :: forall proxy f. (Alt f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => 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)

applyLaws :: (Apply f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following alt properties:

LiftF2 (1)
(<.>) ≡ liftF2 id

applicativeLaws :: (Applicative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => 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 :: forall proxy f. (Foldable f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => 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
foldr1
foldr1 f t ≡ let Just (xs,x) = unsnoc (toList t) in foldr f x xs
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
foldl1
foldl1 f t ≡ let x : xs = toList t in foldl f x xs
toList
toListfoldr (:) []
null
nullfoldr (const (const False)) True
length
lengthgetSum . foldMap (const (Sum 1))

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

functorLaws :: (Functor f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => 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, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => 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

monadPlusLaws :: (MonadPlus f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following monad plus properties:

Left Identity
mplus mzero x ≡ x
Right Identity
mplus x mzero ≡ x
Associativity
mplus a (mplus b c) ≡ mplus (mplus a b) c)
Left Zero
mzero >>= f ≡ mzero
Right Zero
m >> mzeromzero

monadZipLaws :: (MonadZip f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following monadic zipping properties:

Naturality
liftM (f *** g) (mzip ma mb) = mzip (liftM f ma) (liftM g mb)

In the laws above, the infix function *** refers to a typeclass method of Arrow.

plusLaws :: forall proxy f. (Plus f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following alt properties:

Left Identity
zero <!> m ≡ m
Right Identity
m <!> zero ≡ m

extendedPlusLaws :: forall proxy f. (Plus f, Alternative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests everything from altLaws, plus the following:

Congruency
zeroempty

traversableLaws :: (Traversable f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following Traversable properties:

Naturality
t . traverse f ≡ traverse (t . f) for every applicative transformation t
Identity
traverse IdentityIdentity
Composition
traverse (Compose . fmap g . f) ≡ Compose . fmap (traverse g) . traverse f
Sequence Naturality
t . sequenceAsequenceA . fmap t for every applicative transformation t
Sequence Identity
sequenceA . fmap IdentityIdentity
Sequence Composition
sequenceA . fmap ComposeCompose . fmap sequenceA . sequenceA
foldMap
foldMapfoldMapDefault
fmap
fmapfmapDefault

Where an applicative transformation is a function

t :: (Applicative f, Applicative g) => f a -> g a

preserving the Applicative operations, i.e.

  • Identity: t (pure x) ≡ pure x
  • Distributivity: t (x <*> y) ≡ t x <*> t y

Binary type constructors

bifunctorLaws :: forall proxy f. (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) => 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+.

categoryLaws :: forall proxy c. (Category c, forall a b. (Eq a, Eq b) => Eq (c a b), forall a b. (Show a, Show b) => Show (c a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (c a b)) => proxy c -> Laws Source #

Tests the following Category properties:

Right Identity
f . id ≡ f
Left Identity
id . f ≡ f
Associativity
f . (g . h) ≡ (f . g) . h

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

commutativeCategoryLaws :: forall proxy c. (Category c, forall a b. (Eq a, Eq b) => Eq (c a b), forall a b. (Show a, Show b) => Show (c a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (c a b)) => proxy c -> Laws Source #

Test everything from categoryLaws plus the following:

Commutative
f . g ≡ g . f

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

semigroupoidLaws :: forall proxy s. (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) => proxy s -> Laws Source #

Tests the following Semigroupoid properties:

Associativity
f `o' (g `o' h) ≡ (f `o' g) `o' h

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

commutativeSemigroupoidLaws :: forall proxy s. (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) => proxy s -> Laws Source #

Tests everything from semigroupoidLaws plus the following:

Commutative
f `o' g ≡ g `o' f

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

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

Test that a MVector instance obey several laws.

Types

data Laws Source #

A set of laws associated with a typeclass.

Constructors

Laws 

Fields

data Proxy1 (f :: * -> *) Source #

In older versions of GHC, Proxy is not poly-kinded, so we provide Proxy1.

Constructors

Proxy1 

data Proxy2 (f :: * -> * -> *) Source #

In older versions of GHC, Proxy is not poly-kinded, so we provide Proxy2.

Constructors

Proxy2