{- HLINT ignore "Use camelCase" -}
{- HLINT ignore "Redundant bracket" -}

-- |
-- Copyright: © 2022–2024 Jonathan Knowles
-- License: Apache-2.0
--
-- This module provides 'Laws' definitions for classes exported by
-- "Data.Monoid.Monus".
--
module Test.QuickCheck.Classes.Monoid.Monus
    ( monusLaws
    , overlappingGCDMonoidLaws
    )
    where

import Prelude hiding
    ( gcd, null )

import Data.Function
    ( (&) )
import Data.Monoid.GCD
    ( OverlappingGCDMonoid (..) )
import Data.Monoid.Monus
    ( Monus (..) )
import Data.Proxy
    ( Proxy (..) )
import Internal
    ( cover, makeLaw1, makeLaw2, makeLaw3, makeProperty, report )
import Test.QuickCheck
    ( Arbitrary (..), Property )
import Test.QuickCheck.Classes
    ( Laws (..) )
import Test.QuickCheck.Classes.Monoid.GCD
    ( overlappingGCDMonoidLaws )

--------------------------------------------------------------------------------
-- Monus
--------------------------------------------------------------------------------

-- | 'Laws' for instances of 'Monus'.
--
-- Includes the following laws:
--
-- @
-- a '<\>' a '==' 'mempty'
-- @
--
-- @
-- 'mempty' '<\>' a '==' 'mempty'
-- @
--
-- @
-- a '<>' (b '<\>' a) '==' b '<>' (a '<\>' b)
-- @
--
-- @
-- (a '<\>' b) '<\>' c '==' a '<\>' (b '<>' c)
-- @
--
-- @
-- a '<\>' b '==' 'stripPrefixOverlap' b a
-- @
--
-- @
-- a '<\>' b '==' 'stripSuffixOverlap' b a
-- @
--
-- Note that the following superclass laws are __not__ included:
--
-- * 'Test.QuickCheck.Classes.Semigroup.Cancellative.commutativeLaws'
-- * 'Test.QuickCheck.Classes.monoidLaws'
-- * 'Test.QuickCheck.Classes.Monoid.GCD.overlappingGCDMonoidLaws'
--
monusLaws
    :: forall a. (Arbitrary a, Show a, Eq a, Monus a)
    => Proxy a
    -> Laws
monusLaws :: forall a. (Arbitrary a, Show a, Eq a, Monus a) => Proxy a -> Laws
monusLaws Proxy a
_ = String -> [(String, Property)] -> Laws
Laws String
"Monus"
    [ forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"monusLaw_axiom_1"
        (a -> Property
forall a. (Eq a, Monus a, Show a) => a -> Property
monusLaw_axiom_1)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> t) -> (String, Property)
makeLaw1 @a
        String
"monusLaw_axiom_2"
        (a -> Property
forall a. (Eq a, Monus a, Show a) => a -> Property
monusLaw_axiom_2)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> a -> t) -> (String, Property)
makeLaw2 @a
        String
"monusLaw_axiom_3"
        (a -> a -> Property
forall a. (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_axiom_3)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> a -> a -> t) -> (String, Property)
makeLaw3 @a
        String
"monusLaw_axiom_4"
        (a -> a -> a -> Property
forall a. (Eq a, Monus a, Show a) => a -> a -> a -> Property
monusLaw_axiom_4)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> a -> t) -> (String, Property)
makeLaw2 @a
        String
"monusLaw_stripPrefixOverlap"
        (a -> a -> Property
forall a. (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_stripPrefixOverlap)
    , forall a t.
(Arbitrary a, Show a, Eq a, Semigroup a, Testable t) =>
String -> (a -> a -> t) -> (String, Property)
makeLaw2 @a
        String
"monusLaw_stripSuffixOverlap"
        (a -> a -> Property
forall a. (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_stripSuffixOverlap)
    ]

monusLaw_axiom_1
    :: (Eq a, Monus a, Show a) => a -> Property
monusLaw_axiom_1 :: forall a. (Eq a, Monus a, Show a) => a -> Property
monusLaw_axiom_1 a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"a <\\> a == mempty"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Monoid a => a
mempty)
    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
"a == mempty"
        (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Monoid a => a
mempty)
    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
"a /= mempty"
        (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty)
    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
"a <\\> a"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
a)

monusLaw_axiom_2
    :: (Eq a, Monus a, Show a) => a -> Property
monusLaw_axiom_2 :: forall a. (Eq a, Monus a, Show a) => a -> Property
monusLaw_axiom_2 a
a =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"mempty <\\> a == mempty"
        (a
forall a. Monoid a => a
mempty a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Monoid a => a
mempty)
    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
"a == mempty"
        (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Monoid a => a
mempty)
    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
"a /= mempty"
        (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty)
    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
"mempty <\\> a"
        (a
forall a. Monoid a => a
mempty a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
a)

monusLaw_axiom_3
    :: (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_axiom_3 :: forall a. (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_axiom_3 a
a a
b =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"a <> (b <\\> a) == b <> (a <\\> b)"
        (a
a a -> a -> a
forall a. Semigroup a => a -> a -> a
<> (a
b a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
a) a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b a -> a -> a
forall a. Semigroup a => a -> a -> a
<> (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b))
    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
"(a <\\> b) /= mempty"
        ((a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b) a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty)
    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
"(b <\\> a) /= mempty"
        ((a
b a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
a) a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty)
    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
"b <\\> a"
        (a
b a -> a -> a
forall m. Monus m => m -> m -> m
<\\> 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
"a <> (b <\\> a)"
        (a
a a -> a -> a
forall a. Semigroup a => a -> a -> a
<> (a
b a -> a -> a
forall m. Monus m => m -> m -> m
<\\> 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
"a <\\> b"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b)
    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
"b <> (a <\\> b)"
        (a
b a -> a -> a
forall a. Semigroup a => a -> a -> a
<> (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b))

monusLaw_axiom_4
    :: (Eq a, Monus a, Show a) => a -> a -> a -> Property
monusLaw_axiom_4 :: forall a. (Eq a, Monus a, Show a) => a -> a -> a -> Property
monusLaw_axiom_4 a
a a
b a
c =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"(a <\\> b) <\\> c == a <\\> (b <> c)"
        ((a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b) a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
c a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> (a
b a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
c))
    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
"(a <\\> b) <\\> c /= mempty"
        ((a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b) a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
c a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty)
    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
"a <\\> b"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b)
    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
"(a <\\> b) <\\> c"
        ((a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b) a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
c)
    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
"b <> c"
        (a
b a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
c)
    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
"a <\\> (b <> c)"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> (a
b a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
c))

monusLaw_stripPrefixOverlap
    :: (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_stripPrefixOverlap :: forall a. (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_stripPrefixOverlap a
a a
b =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"a <\\> b == stripPrefixOverlap b a"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> a -> a
forall m. OverlappingGCDMonoid m => m -> m -> m
stripPrefixOverlap a
b 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
"a <\\> b /= mempty"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty)
    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
"a <\\> b"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b)
    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
"stripPrefixOverlap b a"
        (a -> a -> a
forall m. OverlappingGCDMonoid m => m -> m -> m
stripPrefixOverlap a
b a
a)

monusLaw_stripSuffixOverlap
    :: (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_stripSuffixOverlap :: forall a. (Eq a, Monus a, Show a) => a -> a -> Property
monusLaw_stripSuffixOverlap a
a a
b =
    String -> Bool -> Property
forall t. Testable t => String -> t -> Property
makeProperty
        String
"a <\\> b == stripSuffixOverlap b a"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> a -> a
forall m. OverlappingGCDMonoid m => m -> m -> m
stripSuffixOverlap a
b 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
"a <\\> b /= mempty"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
forall a. Monoid a => a
mempty)
    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
"a <\\> b"
        (a
a a -> a -> a
forall m. Monus m => m -> m -> m
<\\> a
b)
    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
"stripSuffixOverlap b a"
        (a -> a -> a
forall m. OverlappingGCDMonoid m => m -> m -> m
stripSuffixOverlap a
b a
a)

-- | Convenient synonym for '<\>'.
(<\\>) :: Monus m => m -> m -> m
<\\> :: forall m. Monus m => m -> m -> m
(<\\>) = m -> m -> m
forall m. Monus m => m -> m -> m
(<\>)