quickcheck-monoid-subclasses-0.3.0.7: src/public/Test/QuickCheck/Classes/Monoid/Factorial.hs
{- HLINT ignore "Avoid lambda" -}
{- HLINT ignore "Hoist not" -}
{- HLINT ignore "Redundant bracket" -}
{- HLINT ignore "Use camelCase" -}
{- HLINT ignore "Use const" -}
-- |
-- Copyright: © 2022–2026 Jonathan Knowles
-- License: Apache-2.0
--
-- This module provides 'Laws' definitions for classes exported by
-- "Data.Monoid.Factorial".
--
module Test.QuickCheck.Classes.Monoid.Factorial
( factorialMonoidLaws
)
where
import Prelude hiding
( dropWhile, foldl, length, null, reverse, span, splitAt, takeWhile )
import Data.Bifunctor
( Bifunctor (bimap) )
import Data.Function
( (&) )
import Data.List
( unfoldr )
import Data.Monoid.Factorial
( FactorialMonoid
, inits
, span
, split
, splitAt
, splitPrimePrefix
, splitPrimeSuffix
, tails
)
import Data.Monoid.Null
( null )
import Data.Proxy
( Proxy )
import Data.Semigroup.Factorial
( factors, length, primePrefix, primeSuffix, reverse )
import Data.Tuple
( swap )
import Internal
( cover, makeLaw1, makeProperty, report )
import Test.QuickCheck
( Arbitrary (arbitrary, shrink)
, Fun
, Property
, Testable
, applyFun
, chooseInt
, elements
, forAll
, forAllShrink
)
import Test.QuickCheck.Classes
( Laws (Laws) )
import qualified Data.List as L
--------------------------------------------------------------------------------
-- FactorialMonoid
--------------------------------------------------------------------------------
-- | 'Laws' for instances of 'FactorialMonoid'.
--
-- Includes the following laws:
--
-- @
-- 'null' a '==' 'null' ('factors' a)
-- @
--
-- @
-- 'factors' a '==' \ \ \ \ ('unfoldr' \ \ \ \ 'splitPrimePrefix' a)
-- 'factors' a '==' 'L.reverse' ('unfoldr' ('fmap' 'swap' . 'splitPrimeSuffix') a)
-- @
--
-- @
-- 'reverse' a '==' 'mconcat' ('L.reverse' ('factors' a))
-- @
--
-- @
-- 'primePrefix' a '==' 'maybe' 'mempty' 'fst' ('splitPrimePrefix' a)
-- 'primeSuffix' a '==' 'maybe' 'mempty' 'snd' ('splitPrimeSuffix' a)
-- @
--
-- @
-- 'inits' a '==' 'fmap' 'mconcat' ('L.inits' ('factors' a))
-- 'tails' a '==' 'fmap' 'mconcat' ('L.tails' ('factors' a))
-- @
--
-- @
-- 'span' p a '==' 'bimap' 'mconcat' 'mconcat' ('L.span' p ('factors' a))
-- @
--
-- @
-- 'L.all' ('L.all' ('not' . p) . 'factors') ('split' p a)
-- @
--
-- @
-- 'mconcat' ('L.intersperse' p ('split' ('==' p) a)) '==' a
-- @
--
-- @
-- 'splitAt' i a '==' 'bimap' 'mconcat' 'mconcat' ('L.splitAt' i ('factors' a))
-- @
--
-- Note that the following superclass laws are __not__ included:
--
-- * 'Test.QuickCheck.Classes.Semigroup.Factorial.factorialLaws'
-- * 'Test.QuickCheck.Classes.Monoid.Null.monoidNullLaws'
--
factorialMonoidLaws
:: forall a. (Arbitrary a, Show a, Eq a, FactorialMonoid a)
=> Proxy a
-> Laws
factorialMonoidLaws _ = Laws "FactorialMonoid"
[ makeLaw1 @a
"factorialMonoidLaw_coverage"
(factorialMonoidLaw_coverage)
, makeLaw1 @a
"factorialMonoidLaw_null"
(factorialMonoidLaw_null)
, makeLaw1 @a
"factorialMonoidLaw_splitPrimePrefix"
(factorialMonoidLaw_splitPrimePrefix)
, makeLaw1 @a
"factorialMonoidLaw_splitPrimeSuffix"
(factorialMonoidLaw_splitPrimeSuffix)
, makeLaw1 @a
"factorialMonoidLaw_reverse"
(factorialMonoidLaw_reverse)
, makeLaw1 @a
"factorialMonoidLaw_primePrefix"
(factorialMonoidLaw_primePrefix)
, makeLaw1 @a
"factorialMonoidLaw_primeSuffix"
(factorialMonoidLaw_primeSuffix)
, makeLaw1 @a
"factorialMonoidLaw_inits"
(factorialMonoidLaw_inits)
, makeLaw1 @a
"factorialMonoidLaw_tails"
(factorialMonoidLaw_tails)
, makeLaw1 @a
"factorialMonoidLaw_span"
(factorialMonoidLaw_span)
, makeLaw1 @a
"factorialMonoidLaw_split"
(factorialMonoidLaw_split)
, makeLaw1 @a
"factorialMonoidLaw_split_intersperse"
(factorialMonoidLaw_split_intersperse)
, makeLaw1 @a
"factorialMonoidLaw_splitAt"
(factorialMonoidLaw_splitAt)
]
factorialMonoidLaw_coverage
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_coverage a =
makeProperty
"True"
(True)
& cover
"length a == 0"
(length a == 0)
& cover
"length a == 1"
(length a == 1)
& cover
"length a >= 2"
(length a >= 2)
factorialMonoidLaw_null
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_null a =
makeProperty
"null a == null (factors a)"
(null a == null (factors a))
& report
"null a"
(null a)
& report
"factors a"
(factors a)
& report
"null (factors a)"
(null (factors a))
factorialMonoidLaw_splitPrimePrefix
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimePrefix a =
makeProperty
"factors a == unfoldr splitPrimePrefix a"
(factors a == unfoldr splitPrimePrefix a)
& report
"factors a"
(factors a)
& report
"unfoldr splitPrimePrefix a"
(unfoldr splitPrimePrefix a)
factorialMonoidLaw_splitPrimeSuffix
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimeSuffix a =
makeProperty
"factors a == L.reverse (unfoldr (fmap swap . splitPrimeSuffix) a)"
(factors a == L.reverse (unfoldr (fmap swap . splitPrimeSuffix) a))
& report
"factors a"
(factors a)
& report
"unfoldr (fmap swap . splitPrimeSuffix) a"
(unfoldr (fmap swap . splitPrimeSuffix) a)
& report
"L.reverse (unfoldr (fmap swap . splitPrimeSuffix) a)"
(L.reverse (unfoldr (fmap swap . splitPrimeSuffix) a))
factorialMonoidLaw_reverse
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_reverse a =
makeProperty
"reverse a == mconcat (L.reverse (factors a))"
(reverse a == mconcat (L.reverse (factors a)))
& report
"reverse a"
(reverse a)
& report
"factors a"
(factors a)
& report
"L.reverse (factors a)"
(L.reverse (factors a))
& report
"mconcat (L.reverse (factors a))"
(mconcat (L.reverse (factors a)))
factorialMonoidLaw_primePrefix
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primePrefix a =
makeProperty
"primePrefix a == maybe mempty fst (splitPrimePrefix a)"
(primePrefix a == maybe mempty fst (splitPrimePrefix a))
& report
"primePrefix a"
(primePrefix a)
& report
"splitPrimePrefix a"
(splitPrimePrefix a)
& report
"maybe mempty fst (splitPrimePrefix a)"
(maybe mempty fst (splitPrimePrefix a))
factorialMonoidLaw_primeSuffix
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primeSuffix a =
makeProperty
"primeSuffix a == maybe mempty snd (splitPrimeSuffix a)"
(primeSuffix a == maybe mempty snd (splitPrimeSuffix a))
& report
"primeSuffix a"
(primeSuffix a)
& report
"splitPrimeSuffix a"
(splitPrimeSuffix a)
& report
"maybe mempty snd (splitPrimeSuffix a)"
(maybe mempty snd (splitPrimeSuffix a))
factorialMonoidLaw_inits
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_inits a =
makeProperty
"inits a == fmap mconcat (L.inits (factors a))"
(inits a == fmap mconcat (L.inits (factors a)))
& report
"inits a"
(inits a)
& report
"factors a"
(factors a)
& report
"L.inits (factors a)"
(L.inits (factors a))
& report
"fmap mconcat (L.inits (factors a))"
(fmap mconcat (L.inits (factors a)))
factorialMonoidLaw_tails
:: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_tails a =
makeProperty
"tails a == fmap mconcat (L.tails (factors a))"
(tails a == fmap mconcat (L.tails (factors a)))
& report
"tails a"
(tails a)
& report
"factors a"
(factors a)
& report
"L.tails (factors a)"
(L.tails (factors a))
& report
"fmap mconcat (L.tails (factors a))"
(fmap mconcat (L.tails (factors a)))
factorialMonoidLaw_span
:: forall a. (Eq a, Show a, FactorialMonoid a)
=> a
-> Property
factorialMonoidLaw_span a = withShowableFn $ \p ->
makeProperty
"span p a == bimap mconcat mconcat (L.span p (factors a))"
(span p a == bimap mconcat mconcat (L.span p (factors a)))
& cover
"any p (factors a)"
(any p (factors a))
& cover
"any (not . p) (factors a)"
(any (not . p) (factors a))
& report
"span p a"
(span p a)
& report
"factors a"
(factors a)
& report
"L.span p (factors a)"
(L.span p (factors a))
& report
"bimap mconcat mconcat (L.span p (factors a))"
(bimap mconcat mconcat (L.span p (factors a)))
factorialMonoidLaw_split
:: forall a. (Eq a, Show a, FactorialMonoid a)
=> a
-> Property
factorialMonoidLaw_split a = withShowableFn $ \p ->
makeProperty
"L.all (L.all (not . p) . factors) (split p a)"
(L.all (L.all (not . p) . factors) (split p a))
& cover
"any p (factors a)"
(any p (factors a))
& cover
"any (not . p) (factors a)"
(any (not . p) (factors a))
& report
"split p a"
(split p a)
factorialMonoidLaw_split_intersperse
:: forall a. (Eq a, Show a, FactorialMonoid a)
=> a
-> Property
factorialMonoidLaw_split_intersperse a =
forAll (elements (factors a)) $ \p ->
makeProperty
"mconcat (L.intersperse p (split (== p) a)) == a"
(mconcat (L.intersperse p (split (== p) a)) == a)
& report
"split (== p) a"
(split (== p) a)
& report
"L.intersperse p (split (== p) a)"
(L.intersperse p (split (== p) a))
& report
"mconcat (L.intersperse p (split (== p) a))"
(mconcat (L.intersperse p (split (== p) a)))
factorialMonoidLaw_splitAt
:: forall a. (Eq a, Show a, FactorialMonoid a)
=> a
-> Property
factorialMonoidLaw_splitAt a =
forAll (chooseInt (0, length a)) $ \i ->
makeProperty
"splitAt i a == bimap mconcat mconcat (L.splitAt i (factors a))"
(splitAt i a == bimap mconcat mconcat (L.splitAt i (factors a)))
& report
"splitAt i a"
(splitAt i a)
& report
"factors a"
(factors a)
& report
"L.splitAt i (factors a)"
(L.splitAt i (factors a))
& report
"bimap mconcat mconcat (L.splitAt i (factors a))"
(bimap mconcat mconcat (L.splitAt i (factors a)))
--------------------------------------------------------------------------------
-- Utilities
--------------------------------------------------------------------------------
withShowableFn
:: forall a b t. (Show a, Show b, Arbitrary b, Testable t)
=> ((a -> b) -> t)
-> Property
withShowableFn t =
forAllShrink (arbitrary @(Fun String b)) shrink $
\f -> t ((applyFun f) . show)