    {-
        Copyright 2013-2015 Mario Blazevic

        License: BSD3 (see BSD3-LICENSE.txt file)
    -}

    -- | This module defines the MonoidNull class and some of its instances.
    --

    {-# LANGUAGE Haskell2010, CPP, FlexibleInstances, DefaultSignatures, Trustworthy #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE StandaloneDeriving #-}

    module Data.Monoid.Null (
       MonoidNull(..), PositiveMonoid
       )
    where

    import Data.Functor.Compose (Compose(..))
    import Data.Functor.Const (Const(..))
    import Data.Functor.Identity (Identity(..))
    import Data.Monoid -- (Monoid, First(..), Last(..), Dual(..), Sum(..), Product(..), All(getAll), Any(getAny))
    import Data.Ord (Down(..))
    import Data.Proxy (Proxy)
    import Data.Semigroup (Max, Min, WrappedMonoid(..))
    import qualified Data.Functor.Product as Functor
    import qualified Data.List as List
    import qualified Data.ByteString as ByteString
    import qualified Data.ByteString.Lazy as LazyByteString
    import qualified Data.Text as Text
    import qualified Data.Text.Lazy as LazyText
    import qualified Data.IntMap as IntMap
    import qualified Data.IntSet as IntSet
    import qualified Data.Map as Map
    import qualified Data.Sequence as Sequence
    import qualified Data.Set as Set
    import qualified Data.Vector as Vector
    import GHC.Generics ((:*:)(..), (:.:)(..), K1(..), M1(..), Par1(..), Rec1(..), U1)
    import Numeric.Natural (Natural)

    import Prelude hiding (null)

    -- | Extension of 'Monoid' that allows testing a value for equality with 'mempty'. The following law must hold:
    --
    -- prop> null x == (x == mempty)
    --
    -- Furthermore, the performance of this method should be constant, /i.e./, independent of the length of its argument.
    class Monoid m => MonoidNull m where
       null :: m -> Bool
       default null :: Eq m => m -> Bool
       null = m -> m -> Bool
    forall a. Eq a => a -> a -> Bool
    (==) m
    forall a. Monoid a => a
    mempty

    -- | Subclass of 'Monoid' for types whose values have no inverse, with the exception of 'Data.Monoid.mempty'. More
    -- formally, the class instances must satisfy the following law:
    --
    -- prop> null (x <> y) == (null x && null y)
    class MonoidNull m => PositiveMonoid m

    instance MonoidNull () where
       null :: () -> Bool
    null () = Bool
    True

    instance MonoidNull Ordering where
       null :: Ordering -> Bool
    null = (Ordering -> Ordering -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ordering
    EQ)

    instance MonoidNull All where
       null :: All -> Bool
    null = All -> Bool
    getAll

    instance MonoidNull Any where
       null :: Any -> Bool
    null = Bool -> Bool
    not (Bool -> Bool) -> (Any -> Bool) -> Any -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Any -> Bool
    getAny

    instance MonoidNull (First a) where
       null :: First a -> Bool
    null (First Maybe a
    Nothing) = Bool
    True
       null First a
    _ = Bool
    False

    instance MonoidNull (Last a) where
       null :: Last a -> Bool
    null (Last Maybe a
    Nothing) = Bool
    True
       null Last a
    _ = Bool
    False

    instance MonoidNull a => MonoidNull (Dual a) where
       null :: Dual a -> Bool
    null (Dual a
    a) = a -> Bool
    forall m. MonoidNull m => m -> Bool
    null a
    a

    instance (Num a, Eq a) => MonoidNull (Sum a) where
       null :: Sum a -> Bool
    null (Sum a
    a) = a
    a a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    0

    instance (Num a, Eq a) => MonoidNull (Product a) where
       null :: Product a -> Bool
    null (Product a
    a) = a
    a a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    1

    -- | @since 1.2.5.0
    instance (Ord a, Bounded a) => MonoidNull (Max a)

    -- | @since 1.2.5.0
    instance (Ord a, Bounded a) => MonoidNull (Min a)

    instance Monoid a => MonoidNull (Maybe a) where
       null :: Maybe a -> Bool
    null Maybe a
    Nothing = Bool
    True
       null Maybe a
    _ = Bool
    False

    #if MIN_VERSION_base(4, 11, 0)
    -- | @since 1.2.5.0
    instance MonoidNull a => MonoidNull (Down a) where
       null :: Down a -> Bool
    null (Down a
    a) = a -> Bool
    forall m. MonoidNull m => m -> Bool
    null a
    a
    #endif

    #if MIN_VERSION_base(4, 12, 0)
    -- | @since 1.2.5.0
    instance MonoidNull c => MonoidNull (K1 i c p) where
       null :: K1 i c p -> Bool
    null (K1 c
    c) = c -> Bool
    forall m. MonoidNull m => m -> Bool
    null c
    c

    -- | @since 1.2.5.0
    instance MonoidNull (f p) => MonoidNull (M1 i c f p) where
       null :: M1 i c f p -> Bool
    null (M1 f p
    fp) = f p -> Bool
    forall m. MonoidNull m => m -> Bool
    null f p
    fp

    -- | @since 1.2.5.0
    instance MonoidNull p => MonoidNull (Par1 p) where
       null :: Par1 p -> Bool
    null (Par1 p
    p) = p -> Bool
    forall m. MonoidNull m => m -> Bool
    null p
    p

    -- | @since 1.2.5.0
    instance MonoidNull (f p) => MonoidNull (Rec1 f p) where
       null :: Rec1 f p -> Bool
    null (Rec1 f p
    fp) = f p -> Bool
    forall m. MonoidNull m => m -> Bool
    null f p
    fp

    -- | @since 1.2.5.0
    instance MonoidNull (U1 p) where
       null :: U1 p -> Bool
    null U1 p
    _ = Bool
    True

    -- | @since 1.2.5.0
    instance (MonoidNull (f p), MonoidNull (g p)) => MonoidNull ((:*:) f g p) where
       null :: (:*:) f g p -> Bool
    null (f p
    fp :*: g p
    gp) = f p -> Bool
    forall m. MonoidNull m => m -> Bool
    null f p
    fp Bool -> Bool -> Bool
    && g p -> Bool
    forall m. MonoidNull m => m -> Bool
    null g p
    gp

    -- | @since 1.2.5.0
    instance (MonoidNull (f (g p))) => MonoidNull ((:.:) f g p) where
       null :: (:.:) f g p -> Bool
    null (Comp1 f (g p)
    fgp) = f (g p) -> Bool
    forall m. MonoidNull m => m -> Bool
    null f (g p)
    fgp
    #endif

    #if MIN_VERSION_base(4, 16, 0)
    -- | @since 1.2.5.0
    instance MonoidNull (f (g a)) => MonoidNull (Compose f g a) where
       null :: Compose f g a -> Bool
    null (Compose f (g a)
    fga) = f (g a) -> Bool
    forall m. MonoidNull m => m -> Bool
    null f (g a)
    fga

    -- | @since 1.2.5.0
    instance (MonoidNull (f a), MonoidNull (g a)) => MonoidNull (Functor.Product f g a) where
       null :: Product f g a -> Bool
    null (Functor.Pair f a
    fa g a
    ga) = f a -> Bool
    forall m. MonoidNull m => m -> Bool
    null f a
    fa Bool -> Bool -> Bool
    && g a -> Bool
    forall m. MonoidNull m => m -> Bool
    null g a
    ga
    #endif

    -- | @since 1.2.5.0
    deriving instance MonoidNull a => MonoidNull (Const a b)

    -- | @since 1.2.5.0
    deriving instance MonoidNull a => MonoidNull (Identity a)

    -- | @since 1.2.5.0
    instance MonoidNull a => MonoidNull (WrappedMonoid a) where
       null :: WrappedMonoid a -> Bool
    null (WrapMonoid a
    a) = a -> Bool
    forall m. MonoidNull m => m -> Bool
    null a
    a

    -- | @since 1.2.5.0
    instance MonoidNull (Proxy a) where
       null :: Proxy a -> Bool
    null Proxy a
    _ = Bool
    True

    instance (MonoidNull a, MonoidNull b) => MonoidNull (a, b) where
       null :: (a, b) -> Bool
    null (a
    a, b
    b) = a -> Bool
    forall m. MonoidNull m => m -> Bool
    null a
    a Bool -> Bool -> Bool
    && b -> Bool
    forall m. MonoidNull m => m -> Bool
    null b
    b

    instance (MonoidNull a, MonoidNull b, MonoidNull c) => MonoidNull (a, b, c) where
       null :: (a, b, c) -> Bool
    null (a
    a, b
    b, c
    c) = a -> Bool
    forall m. MonoidNull m => m -> Bool
    null a
    a Bool -> Bool -> Bool
    && b -> Bool
    forall m. MonoidNull m => m -> Bool
    null b
    b Bool -> Bool -> Bool
    && c -> Bool
    forall m. MonoidNull m => m -> Bool
    null c
    c

    instance (MonoidNull a, MonoidNull b, MonoidNull c, MonoidNull d) => MonoidNull (a, b, c, d) where
       null :: (a, b, c, d) -> Bool
    null (a
    a, b
    b, c
    c, d
    d) = a -> Bool
    forall m. MonoidNull m => m -> Bool
    null a
    a Bool -> Bool -> Bool
    && b -> Bool
    forall m. MonoidNull m => m -> Bool
    null b
    b Bool -> Bool -> Bool
    && c -> Bool
    forall m. MonoidNull m => m -> Bool
    null c
    c Bool -> Bool -> Bool
    && d -> Bool
    forall m. MonoidNull m => m -> Bool
    null d
    d

    -- | @since 1.2.5.0
    instance (MonoidNull a, MonoidNull b, MonoidNull c, MonoidNull d, MonoidNull e) => MonoidNull (a, b, c, d, e) where
       null :: (a, b, c, d, e) -> Bool
    null (a
    a, b
    b, c
    c, d
    d, e
    e) = a -> Bool
    forall m. MonoidNull m => m -> Bool
    null a
    a Bool -> Bool -> Bool
    && b -> Bool
    forall m. MonoidNull m => m -> Bool
    null b
    b Bool -> Bool -> Bool
    && c -> Bool
    forall m. MonoidNull m => m -> Bool
    null c
    c Bool -> Bool -> Bool
    && d -> Bool
    forall m. MonoidNull m => m -> Bool
    null d
    d Bool -> Bool -> Bool
    && e -> Bool
    forall m. MonoidNull m => m -> Bool
    null e
    e

    instance MonoidNull [x] where
       null :: [x] -> Bool
    null = [x] -> Bool
    forall x. [x] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    List.null

    instance MonoidNull ByteString.ByteString where
       null :: ByteString -> Bool
    null = ByteString -> Bool
    ByteString.null
       {-# INLINE null #-}

    instance MonoidNull LazyByteString.ByteString where
       null :: ByteString -> Bool
    null = ByteString -> Bool
    LazyByteString.null
       {-# INLINE null #-}

    instance MonoidNull Text.Text where
       null :: Text -> Bool
    null = Text -> Bool
    Text.null
       {-# INLINE null #-}

    instance MonoidNull LazyText.Text where
       null :: Text -> Bool
    null = Text -> Bool
    LazyText.null
       {-# INLINE null #-}

    instance Ord k => MonoidNull (Map.Map k v) where
       null :: Map k v -> Bool
    null = Map k v -> Bool
    forall k a. Map k a -> Bool
    Map.null

    instance MonoidNull (IntMap.IntMap v) where
       null :: IntMap v -> Bool
    null = IntMap v -> Bool
    forall v. IntMap v -> Bool
    IntMap.null

    instance MonoidNull IntSet.IntSet where
       null :: IntSet -> Bool
    null = IntSet -> Bool
    IntSet.null

    instance MonoidNull (Sequence.Seq a) where
       null :: Seq a -> Bool
    null = Seq a -> Bool
    forall a. Seq a -> Bool
    Sequence.null

    instance Ord a => MonoidNull (Set.Set a) where
       null :: Set a -> Bool
    null = Set a -> Bool
    forall a. Set a -> Bool
    Set.null

    instance MonoidNull (Vector.Vector a) where
       null :: Vector a -> Bool
    null = Vector a -> Bool
    forall a. Vector a -> Bool
    Vector.null

    instance PositiveMonoid ()
    instance PositiveMonoid Ordering
    instance PositiveMonoid All
    instance PositiveMonoid Any
    instance PositiveMonoid ByteString.ByteString
    instance PositiveMonoid LazyByteString.ByteString
    instance PositiveMonoid Text.Text
    instance PositiveMonoid LazyText.Text
    instance PositiveMonoid (Product Natural)
    instance PositiveMonoid (Sum Natural)
    -- | @since 1.2.5.0
    instance (Ord a, Bounded a) => PositiveMonoid (Min a)
    -- | @since 1.2.5.0
    instance (Ord a, Bounded a) => PositiveMonoid (Max a)
    instance Monoid a => PositiveMonoid (Maybe a)
    instance PositiveMonoid (First a)
    instance PositiveMonoid (Last a)
    instance PositiveMonoid a => PositiveMonoid (Dual a)
    instance PositiveMonoid [x]
    instance Ord k => PositiveMonoid (Map.Map k v)
    instance PositiveMonoid (IntMap.IntMap v)
    instance PositiveMonoid IntSet.IntSet
    instance PositiveMonoid (Sequence.Seq a)
    instance Ord a => PositiveMonoid (Set.Set a)
    instance PositiveMonoid (Vector.Vector a)
    -- | @since 1.2.5.0
    instance PositiveMonoid r => PositiveMonoid (Const r a)
    -- | @since 1.2.5.0
    instance PositiveMonoid a => PositiveMonoid (Identity a)
    -- | @since 1.2.5.0
    instance PositiveMonoid a => PositiveMonoid (WrappedMonoid a)
    -- | @since 1.2.5.0
    instance PositiveMonoid (Proxy a)

    #if MIN_VERSION_base(4, 11, 0)
    -- | @since 1.2.5.0
    instance PositiveMonoid a => PositiveMonoid (Down a)
    #endif

    #if MIN_VERSION_base(4, 12, 0)
    -- | @since 1.2.5.0
    instance PositiveMonoid c => PositiveMonoid (K1 i c p)
    -- | @since 1.2.5.0
    instance PositiveMonoid (f p) => PositiveMonoid (M1 i c f p)
    -- | @since 1.2.5.0
    instance PositiveMonoid p => PositiveMonoid (Par1 p)
    -- | @since 1.2.5.0
    instance PositiveMonoid (f p) => PositiveMonoid (Rec1 f p)
    -- | @since 1.2.5.0
    instance PositiveMonoid (U1 p)
    -- | @since 1.2.5.0
    instance (PositiveMonoid (f (g p))) => PositiveMonoid ((:.:) f g p)
    #endif

    #if MIN_VERSION_base(4, 16, 0)
    -- | @since 1.2.5.0
    instance PositiveMonoid (f (g a)) => PositiveMonoid (Compose f g a)
    #endif

    -- The possible tuple instances would be overlapping, so we leave the choice to the user.
    --
    -- instance (PositiveMonoid a, Monoid b) => PositiveMonoid (a, b)
    -- instance (Monoid a, PositiveMonoid b) => PositiveMonoid (a, b)