diff --git a/CHANGELOG.md b/CHANGELOG.md index 4672c1a..007d6f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +Unreleased (Minor) +------------------ + +* `Data.Monoid.Null.MonoidNull` now has a default implementation +* Add instances of `MonoidNull` and (where appropriate) `PositiveMonoid` for: + - `(a, b, c, d, e)` + - `Data.Functor.Compose f g a` + - `Data.Functor.Const r a` + - `Data.Functor.Identity a` + - `Data.Functor.Product f g a` + - `Data.Ord.Down a` + - `Data.Proxy.Proxy a` + - `Data.Semigroup.Max a` + - `Data.Semigroup.Min a` + - `Data.Semigroup.WrappedMonoid a` + - `GHC.Generics.(:*:) f g a` + - `GHC.Generics.(:.:) f g a` + - `GHC.Generics.K1 i c p` + - `GHC.Generics.M1 i c f p` + - `GHC.Generics.Par1 p` + - `GHC.Generics.Rec1 f p` + - `GHC.Generics.U1 p` + Version 1.2.4.1 --------------- * Bumped the `text` dependency upper bounds diff --git a/src/Data/Monoid/Null.hs b/src/Data/Monoid/Null.hs index c23d9b0..75f1c5a 100644 --- a/src/Data/Monoid/Null.hs +++ b/src/Data/Monoid/Null.hs @@ -1,20 +1,27 @@ -{- +{- 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, FlexibleInstances, Trustworthy #-} +{-# LANGUAGE Haskell2010, CPP, FlexibleInstances, DefaultSignatures, Trustworthy #-} 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 @@ -26,21 +33,24 @@ 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 = (==) 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 @@ -73,10 +83,78 @@ instance (Num a, Eq a) => MonoidNull (Sum a) where instance (Num a, Eq a) => MonoidNull (Product a) where null (Product a) = 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 Nothing = True null _ = False +#if MIN_VERSION_base(4, 11, 0) +-- | @since 1.2.5.0 +instance MonoidNull a => MonoidNull (Down a) where + null (Down a) = null 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 c) = null c + +-- | @since 1.2.5.0 +instance MonoidNull (f p) => MonoidNull (M1 i c f p) where + null (M1 fp) = null fp + +-- | @since 1.2.5.0 +instance MonoidNull p => MonoidNull (Par1 p) where + null (Par1 p) = null p + +-- | @since 1.2.5.0 +instance MonoidNull (f p) => MonoidNull (Rec1 f p) where + null (Rec1 fp) = null fp + +-- | @since 1.2.5.0 +instance MonoidNull (U1 p) where + null _ = True + +-- | @since 1.2.5.0 +instance (MonoidNull (f p), MonoidNull (g p)) => MonoidNull ((:*:) f g p) where + null (fp :*: gp) = null fp && null gp + +-- | @since 1.2.5.0 +instance (MonoidNull (f (g p))) => MonoidNull ((:.:) f g p) where + null (Comp1 fgp) = null 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 fga) = null fga + +-- | @since 1.2.5.0 +instance (MonoidNull (f a), MonoidNull (g a)) => MonoidNull (Functor.Product f g a) where + null (Functor.Pair fa ga) = null fa && null ga +#endif + +-- | @since 1.2.5.0 +instance MonoidNull r => MonoidNull (Const r a) where + null (Const r) = null r + +-- | @since 1.2.5.0 +instance MonoidNull a => MonoidNull (Identity a) where + null (Identity a) = null a + +-- | @since 1.2.5.0 +instance MonoidNull a => MonoidNull (WrappedMonoid a) where + null (WrapMonoid a) = null a + +-- | @since 1.2.5.0 +instance MonoidNull (Proxy a) where + null _ = True + instance (MonoidNull a, MonoidNull b) => MonoidNull (a, b) where null (a, b) = null a && null b @@ -86,6 +164,10 @@ instance (MonoidNull a, MonoidNull b, MonoidNull c) => MonoidNull (a, b, c) wher instance (MonoidNull a, MonoidNull b, MonoidNull c, MonoidNull d) => MonoidNull (a, b, c, d) where null (a, b, c, d) = null a && null b && null c && null 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) = null a && null b && null c && null d && null e + instance MonoidNull [x] where null = List.null @@ -133,6 +215,10 @@ 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) @@ -144,6 +230,39 @@ 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. --