{-# LANGUAGE ExistentialQuantification #-}

-- | Monoids using `.&&.` and `.||.`.
--
-- They satisfy monoid laws with respect to the `isSuccess` unless one is using
-- `checkCoverage` (see test for a counterexample).
--
module Test.QuickCheck.Monoids
  ( All (..)
  , Any (..)
  ) where

import Data.List.NonEmpty as NonEmpty
import Data.Semigroup (Semigroup (..))
import Test.QuickCheck

-- | Conjunction monoid build with `.&&.`.
--
-- Use `property @All` as an accessor which doesn't leak
-- existential variables.
--
data All = forall p. Testable p => All { ()
getAll :: p }

instance Testable All where
    property :: All -> Property
property (All p
p) = p -> Property
forall prop. Testable prop => prop -> Property
property p
p

instance Semigroup All where
    All p
p <> :: All -> All -> All
<> All p
p' = Property -> All
forall p. Testable p => p -> All
All (p
p p -> p -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. p
p')
    sconcat :: NonEmpty All -> All
sconcat = Property -> All
forall p. Testable p => p -> All
All (Property -> All)
-> (NonEmpty All -> Property) -> NonEmpty All -> All
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [All] -> Property
forall prop. Testable prop => [prop] -> Property
conjoin ([All] -> Property)
-> (NonEmpty All -> [All]) -> NonEmpty All -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty All -> [All]
forall a. NonEmpty a -> [a]
NonEmpty.toList

instance Monoid All where
    mempty :: All
mempty = Bool -> All
forall p. Testable p => p -> All
All Bool
True
    mconcat :: [All] -> All
mconcat = Property -> All
forall p. Testable p => p -> All
All (Property -> All) -> ([All] -> Property) -> [All] -> All
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [All] -> Property
forall prop. Testable prop => [prop] -> Property
conjoin


-- | Disjunction monoid build with `.||.`.
--
-- Use `property @Any` as an accessor which doesn't leak
-- existential variables.
--
data Any = forall p. Testable p => Any { ()
getAny :: p }

instance Testable Any where
    property :: Any -> Property
property (Any p
p) = p -> Property
forall prop. Testable prop => prop -> Property
property p
p

instance Semigroup Any where
    Any p
p <> :: Any -> Any -> Any
<> Any p
p' = Property -> Any
forall p. Testable p => p -> Any
Any (p
p p -> p -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.||. p
p')
    sconcat :: NonEmpty Any -> Any
sconcat = Property -> Any
forall p. Testable p => p -> Any
Any (Property -> Any)
-> (NonEmpty Any -> Property) -> NonEmpty Any -> Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Any] -> Property
forall prop. Testable prop => [prop] -> Property
disjoin ([Any] -> Property)
-> (NonEmpty Any -> [Any]) -> NonEmpty Any -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Any -> [Any]
forall a. NonEmpty a -> [a]
NonEmpty.toList

instance Monoid Any where
    mempty :: Any
mempty = Bool -> Any
forall p. Testable p => p -> Any
Any Bool
False
    mconcat :: [Any] -> Any
mconcat = Property -> Any
forall p. Testable p => p -> Any
Any (Property -> Any) -> ([Any] -> Property) -> [Any] -> Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Any] -> Property
forall prop. Testable prop => [prop] -> Property
disjoin