{- HLINT ignore "Avoid lambda" -}
{- HLINT ignore "Hoist not" -}
{- HLINT ignore "Redundant bracket" -}
{- HLINT ignore "Use camelCase" -}
{- HLINT ignore "Use const" -}

-- |
-- Copyright: © 2022–2024 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 :: forall a.
(Arbitrary a, Show a, Eq a, FactorialMonoid a) =>
Proxy a -> Laws
factorialMonoidLaws Proxy a
_ = String -> [(String, Property)] -> Laws
Laws String
"FactorialMonoid"
    [ forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_coverage"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_coverage)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_null"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_null)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_splitPrimePrefix"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimePrefix)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_splitPrimeSuffix"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimeSuffix)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_reverse"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_reverse)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_primePrefix"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primePrefix)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_primeSuffix"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primeSuffix)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_inits"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_inits)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_tails"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_tails)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_span"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_span)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_split"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_split)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_split_intersperse"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_split_intersperse)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"factorialMonoidLaw_splitAt"
        (a -> Property
forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitAt)
    ]

factorialMonoidLaw_coverage
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_coverage :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_coverage a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"True"
        (Bool
True)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall t. Testable t => String -> Bool -> t -> Property
cover
        String
"length a == 0"
        (a -> Int
forall m. Factorial m => m -> Int
length a
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall t. Testable t => String -> Bool -> t -> Property
cover
        String
"length a == 1"
        (a -> Int
forall m. Factorial m => m -> Int
length a
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall t. Testable t => String -> Bool -> t -> Property
cover
        String
"length a >= 2"
        (a -> Int
forall m. Factorial m => m -> Int
length a
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2)

factorialMonoidLaw_null
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_null :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_null a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"null a == null (factors a)"
        (a -> Bool
forall m. MonoidNull m => m -> Bool
null a
a Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> Bool
forall m. MonoidNull m => m -> Bool
null (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"null a"
        (a -> Bool
forall m. MonoidNull m => m -> Bool
null a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"factors a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"null (factors a)"
        ([a] -> Bool
forall m. MonoidNull m => m -> Bool
null (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))

factorialMonoidLaw_splitPrimePrefix
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimePrefix :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimePrefix a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"factors a == unfoldr splitPrimePrefix a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a [a] -> [a] -> Bool
forall a. Eq a => a -> a -> Bool
== (a -> Maybe (a, a)) -> a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimePrefix a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"factors a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"unfoldr splitPrimePrefix a"
        ((a -> Maybe (a, a)) -> a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimePrefix a
a)

factorialMonoidLaw_splitPrimeSuffix
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimeSuffix :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitPrimeSuffix a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"factors a == L.reverse (unfoldr (fmap swap . splitPrimeSuffix) a)"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a [a] -> [a] -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> [a]
forall a. [a] -> [a]
L.reverse ((a -> Maybe (a, a)) -> a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (((a, a) -> (a, a)) -> Maybe (a, a) -> Maybe (a, a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, a) -> (a, a)
forall a b. (a, b) -> (b, a)
swap (Maybe (a, a) -> Maybe (a, a))
-> (a -> Maybe (a, a)) -> a -> Maybe (a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimeSuffix) a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"factors a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"unfoldr (fmap swap . splitPrimeSuffix) a"
        ((a -> Maybe (a, a)) -> a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (((a, a) -> (a, a)) -> Maybe (a, a) -> Maybe (a, a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, a) -> (a, a)
forall a b. (a, b) -> (b, a)
swap (Maybe (a, a) -> Maybe (a, a))
-> (a -> Maybe (a, a)) -> a -> Maybe (a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimeSuffix) a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"L.reverse (unfoldr (fmap swap . splitPrimeSuffix) a)"
        ([a] -> [a]
forall a. [a] -> [a]
L.reverse ((a -> Maybe (a, a)) -> a -> [a]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (((a, a) -> (a, a)) -> Maybe (a, a) -> Maybe (a, a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, a) -> (a, a)
forall a b. (a, b) -> (b, a)
swap (Maybe (a, a) -> Maybe (a, a))
-> (a -> Maybe (a, a)) -> a -> Maybe (a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimeSuffix) a
a))

factorialMonoidLaw_reverse
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_reverse :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_reverse a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"reverse a == mconcat (L.reverse (factors a))"
        (a -> a
forall m. Factorial m => m -> m
reverse a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> a
forall a. Monoid a => [a] -> a
mconcat ([a] -> [a]
forall a. [a] -> [a]
L.reverse (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> a -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"reverse a"
        (a -> a
forall m. Factorial m => m -> m
reverse a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"factors a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"L.reverse (factors a)"
        ([a] -> [a]
forall a. [a] -> [a]
L.reverse (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> a -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"mconcat (L.reverse (factors a))"
        ([a] -> a
forall a. Monoid a => [a] -> a
mconcat ([a] -> [a]
forall a. [a] -> [a]
L.reverse (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))

factorialMonoidLaw_primePrefix
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primePrefix :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primePrefix a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"primePrefix a == maybe mempty fst (splitPrimePrefix a)"
        (a -> a
forall m. Factorial m => m -> m
primePrefix a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> ((a, a) -> a) -> Maybe (a, a) -> a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a
forall a. Monoid a => a
mempty (a, a) -> a
forall a b. (a, b) -> a
fst (a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimePrefix a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> a -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"primePrefix a"
        (a -> a
forall m. Factorial m => m -> m
primePrefix a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Maybe (a, a) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"splitPrimePrefix a"
        (a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimePrefix a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> a -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"maybe mempty fst (splitPrimePrefix a)"
        (a -> ((a, a) -> a) -> Maybe (a, a) -> a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a
forall a. Monoid a => a
mempty (a, a) -> a
forall a b. (a, b) -> a
fst (a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimePrefix a
a))

factorialMonoidLaw_primeSuffix
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primeSuffix :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_primeSuffix a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"primeSuffix a == maybe mempty snd (splitPrimeSuffix a)"
        (a -> a
forall m. Factorial m => m -> m
primeSuffix a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> ((a, a) -> a) -> Maybe (a, a) -> a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a
forall a. Monoid a => a
mempty (a, a) -> a
forall a b. (a, b) -> b
snd (a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimeSuffix a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> a -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"primeSuffix a"
        (a -> a
forall m. Factorial m => m -> m
primeSuffix a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Maybe (a, a) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"splitPrimeSuffix a"
        (a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimeSuffix a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> a -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"maybe mempty snd (splitPrimeSuffix a)"
        (a -> ((a, a) -> a) -> Maybe (a, a) -> a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a
forall a. Monoid a => a
mempty (a, a) -> a
forall a b. (a, b) -> b
snd (a -> Maybe (a, a)
forall m. FactorialMonoid m => m -> Maybe (m, m)
splitPrimeSuffix a
a))

factorialMonoidLaw_inits
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_inits :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_inits a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"inits a == fmap mconcat (L.inits (factors a))"
        (a -> [a]
forall m. FactorialMonoid m => m -> [m]
inits a
a [a] -> [a] -> Bool
forall a. Eq a => a -> a -> Bool
== ([a] -> a) -> [[a]] -> [a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> a
forall a. Monoid a => [a] -> a
mconcat ([a] -> [[a]]
forall a. [a] -> [[a]]
L.inits (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"inits a"
        (a -> [a]
forall m. FactorialMonoid m => m -> [m]
inits a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"factors a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [[a]] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"L.inits (factors a)"
        ([a] -> [[a]]
forall a. [a] -> [[a]]
L.inits (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"fmap mconcat (L.inits (factors a))"
        (([a] -> a) -> [[a]] -> [a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> a
forall a. Monoid a => [a] -> a
mconcat ([a] -> [[a]]
forall a. [a] -> [[a]]
L.inits (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))

factorialMonoidLaw_tails
    :: (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_tails :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_tails a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"tails a == fmap mconcat (L.tails (factors a))"
        (a -> [a]
forall m. FactorialMonoid m => m -> [m]
tails a
a [a] -> [a] -> Bool
forall a. Eq a => a -> a -> Bool
== ([a] -> a) -> [[a]] -> [a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> a
forall a. Monoid a => [a] -> a
mconcat ([a] -> [[a]]
forall a. [a] -> [[a]]
L.tails (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"tails a"
        (a -> [a]
forall m. FactorialMonoid m => m -> [m]
tails a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"factors a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [[a]] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"L.tails (factors a)"
        ([a] -> [[a]]
forall a. [a] -> [[a]]
L.tails (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"fmap mconcat (L.tails (factors a))"
        (([a] -> a) -> [[a]] -> [a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> a
forall a. Monoid a => [a] -> a
mconcat ([a] -> [[a]]
forall a. [a] -> [[a]]
L.tails (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))

factorialMonoidLaw_span
    :: forall a. (Eq a, Show a, FactorialMonoid a)
    => a
    -> Property
factorialMonoidLaw_span :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_span a
a = ((a -> Bool) -> Property) -> Property
forall a b t.
(Show a, Show b, Arbitrary b, Testable t) =>
((a -> b) -> t) -> Property
withShowableFn (((a -> Bool) -> Property) -> Property)
-> ((a -> Bool) -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \a -> Bool
p ->
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"span p a == bimap mconcat mconcat (L.span p (factors a))"
        ((a -> Bool) -> a -> (a, a)
forall m. FactorialMonoid m => (m -> Bool) -> m -> (m, m)
span a -> Bool
p a
a (a, a) -> (a, a) -> Bool
forall a. Eq a => a -> a -> Bool
== ([a] -> a) -> ([a] -> a) -> ([a], [a]) -> (a, a)
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap [a] -> a
forall a. Monoid a => [a] -> a
mconcat [a] -> a
forall a. Monoid a => [a] -> a
mconcat ((a -> Bool) -> [a] -> ([a], [a])
forall a. (a -> Bool) -> [a] -> ([a], [a])
L.span a -> Bool
p (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall t. Testable t => String -> Bool -> t -> Property
cover
        String
"any p (factors a)"
        ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any a -> Bool
p (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall t. Testable t => String -> Bool -> t -> Property
cover
        String
"any (not . p) (factors a)"
        ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p) (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> (a, a) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"span p a"
        ((a -> Bool) -> a -> (a, a)
forall m. FactorialMonoid m => (m -> Bool) -> m -> (m, m)
span a -> Bool
p a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"factors a"
        (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> ([a], [a]) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"L.span p (factors a)"
        ((a -> Bool) -> [a] -> ([a], [a])
forall a. (a -> Bool) -> [a] -> ([a], [a])
L.span a -> Bool
p (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> (a, a) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"bimap mconcat mconcat (L.span p (factors a))"
        (([a] -> a) -> ([a] -> a) -> ([a], [a]) -> (a, a)
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap [a] -> a
forall a. Monoid a => [a] -> a
mconcat [a] -> a
forall a. Monoid a => [a] -> a
mconcat ((a -> Bool) -> [a] -> ([a], [a])
forall a. (a -> Bool) -> [a] -> ([a], [a])
L.span a -> Bool
p (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))

factorialMonoidLaw_split
    :: forall a. (Eq a, Show a, FactorialMonoid a)
    => a
    -> Property
factorialMonoidLaw_split :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_split a
a = ((a -> Bool) -> Property) -> Property
forall a b t.
(Show a, Show b, Arbitrary b, Testable t) =>
((a -> b) -> t) -> Property
withShowableFn (((a -> Bool) -> Property) -> Property)
-> ((a -> Bool) -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \a -> Bool
p ->
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"L.all (L.all (not . p) . factors) (split p a)"
        ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
L.all ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
L.all (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p) ([a] -> Bool) -> (a -> [a]) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [a]
forall m. Factorial m => m -> [m]
factors) ((a -> Bool) -> a -> [a]
forall m. FactorialMonoid m => (m -> Bool) -> m -> [m]
split a -> Bool
p a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall t. Testable t => String -> Bool -> t -> Property
cover
        String
"any p (factors a)"
        ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any a -> Bool
p (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> Bool -> Property -> Property
forall t. Testable t => String -> Bool -> t -> Property
cover
        String
"any (not . p) (factors a)"
        ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Bool -> Bool
not (Bool -> Bool) -> (a -> Bool) -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p) (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
    Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
        String
"split p a"
        ((a -> Bool) -> a -> [a]
forall m. FactorialMonoid m => (m -> Bool) -> m -> [m]
split a -> Bool
p a
a)

factorialMonoidLaw_split_intersperse
    :: forall a. (Eq a, Show a, FactorialMonoid a)
    => a
    -> Property
factorialMonoidLaw_split_intersperse :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_split_intersperse a
a =
    Gen a -> (a -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll ([a] -> Gen a
forall a. HasCallStack => [a] -> Gen a
elements (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)) ((a -> Property) -> Property) -> (a -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \a
p ->
        String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
            String
"mconcat (L.intersperse p (split (== p) a)) == a"
            ([a] -> a
forall a. Monoid a => [a] -> a
mconcat (a -> [a] -> [a]
forall a. a -> [a] -> [a]
L.intersperse a
p ((a -> Bool) -> a -> [a]
forall m. FactorialMonoid m => (m -> Bool) -> m -> [m]
split (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
p) a
a)) a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a)
        Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
            String
"split (== p) a"
            ((a -> Bool) -> a -> [a]
forall m. FactorialMonoid m => (m -> Bool) -> m -> [m]
split (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
p) a
a)
        Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
            String
"L.intersperse p (split (== p) a)"
            (a -> [a] -> [a]
forall a. a -> [a] -> [a]
L.intersperse a
p ((a -> Bool) -> a -> [a]
forall m. FactorialMonoid m => (m -> Bool) -> m -> [m]
split (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
p) a
a))
        Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> a -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
            String
"mconcat (L.intersperse p (split (== p) a))"
            ([a] -> a
forall a. Monoid a => [a] -> a
mconcat (a -> [a] -> [a]
forall a. a -> [a] -> [a]
L.intersperse a
p ((a -> Bool) -> a -> [a]
forall m. FactorialMonoid m => (m -> Bool) -> m -> [m]
split (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
p) a
a)))

factorialMonoidLaw_splitAt
    :: forall a. (Eq a, Show a, FactorialMonoid a)
    => a
    -> Property
factorialMonoidLaw_splitAt :: forall a. (Eq a, Show a, FactorialMonoid a) => a -> Property
factorialMonoidLaw_splitAt a
a =
    Gen Int -> (Int -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
forAll ((Int, Int) -> Gen Int
chooseInt (Int
0, a -> Int
forall m. Factorial m => m -> Int
length a
a)) ((Int -> Property) -> Property) -> (Int -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \Int
i ->
        String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
            String
"splitAt i a == bimap mconcat mconcat (L.splitAt i (factors a))"
            (Int -> a -> (a, a)
forall m. FactorialMonoid m => Int -> m -> (m, m)
splitAt Int
i a
a (a, a) -> (a, a) -> Bool
forall a. Eq a => a -> a -> Bool
== ([a] -> a) -> ([a] -> a) -> ([a], [a]) -> (a, a)
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap [a] -> a
forall a. Monoid a => [a] -> a
mconcat [a] -> a
forall a. Monoid a => [a] -> a
mconcat (Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
L.splitAt Int
i (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))
        Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> (a, a) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
            String
"splitAt i a"
            (Int -> a -> (a, a)
forall m. FactorialMonoid m => Int -> m -> (m, m)
splitAt Int
i a
a)
        Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> [a] -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
            String
"factors a"
            (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)
        Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> ([a], [a]) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
            String
"L.splitAt i (factors a)"
            (Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
L.splitAt Int
i (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a))
        Property -> (Property -> Property) -> Property
forall a b. a -> (a -> b) -> b
& String -> (a, a) -> Property -> Property
forall a prop.
(Show a, Testable prop) =>
String -> a -> prop -> Property
report
            String
"bimap mconcat mconcat (L.splitAt i (factors a))"
            (([a] -> a) -> ([a] -> a) -> ([a], [a]) -> (a, a)
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap [a] -> a
forall a. Monoid a => [a] -> a
mconcat [a] -> a
forall a. Monoid a => [a] -> a
mconcat (Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
L.splitAt Int
i (a -> [a]
forall m. Factorial m => m -> [m]
factors a
a)))

--------------------------------------------------------------------------------
-- Utilities
--------------------------------------------------------------------------------

withShowableFn
    :: forall a b t. (Show a, Show b, Arbitrary b, Testable t)
    => ((a -> b) -> t)
    -> Property
withShowableFn :: forall a b t.
(Show a, Show b, Arbitrary b, Testable t) =>
((a -> b) -> t) -> Property
withShowableFn (a -> b) -> t
t =
    Gen (Fun String b)
-> (Fun String b -> [Fun String b])
-> (Fun String b -> t)
-> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> [a]) -> (a -> prop) -> Property
forAllShrink (forall a. Arbitrary a => Gen a
arbitrary @(Fun String b)) Fun String b -> [Fun String b]
forall a. Arbitrary a => a -> [a]
shrink ((Fun String b -> t) -> Property)
-> (Fun String b -> t) -> Property
forall a b. (a -> b) -> a -> b
$
        \Fun String b
f -> (a -> b) -> t
t ((Fun String b -> String -> b
forall a b. Fun a b -> a -> b
applyFun Fun String b
f) (String -> b) -> (a -> String) -> a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show)