{-# LANGUAGE DataKinds #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE LinearTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE NoImplicitPrelude #-} {-# OPTIONS_GHC -Wno-orphans #-} {-# OPTIONS_HADDOCK hide #-} -- | This module provides linear versions of 'Monoid'. -- -- To learn about how these classic monoids work, go to this school of haskell -- [post](https://www.schoolofhaskell.com/user/mgsloan/monoids-tour). module Data.Monoid.Linear.Internal.Monoid ( -- * Monoid operations Monoid (..), mconcat, mappend, -- Cannot export Data.Monoid.{First,Last} because of the name clash with Data.Semigroup.{First,Last} ) where import Data.Functor.Compose (Compose (Compose)) import qualified Data.Functor.Compose as Functor import Data.Functor.Const (Const) import Data.Functor.Identity (Identity (Identity)) import Data.Functor.Product (Product (Pair)) import qualified Data.Functor.Product as Functor import qualified Data.Monoid as Monoid import Data.Monoid.Linear.Internal.Semigroup import Data.Ord (Down (Down)) import Data.Proxy (Proxy (Proxy)) import Data.Unrestricted.Linear.Internal.Consumable (Consumable) import qualified Data.Unrestricted.Linear.Internal.Ur as Ur import GHC.Types hiding (Any) import Prelude.Linear.Internal import Prelude (Maybe (Nothing)) import qualified Prelude -- | A linear monoid is a linear semigroup with an identity on the binary -- operation. -- -- Laws (same as 'Data.Monoid.Monoid'): -- * ∀ x ∈ G, x <> mempty = mempty <> x = x class (Semigroup a) => Monoid a where {-# MINIMAL mempty #-} mempty :: a instance (Prelude.Semigroup a, Monoid a) => Prelude.Monoid (NonLinear a) where mempty = NonLinear mempty -- convenience redefine mconcat :: (Monoid a) => [a] %1 -> a mconcat (xs' :: [a]) = go mempty xs' where go :: a %1 -> [a] %1 -> a go acc [] = acc go acc (x : xs) = go (acc <> x) xs mappend :: (Monoid a) => a %1 -> a %1 -> a mappend = (<>) --------------- -- Instances -- --------------- instance Prelude.Monoid (Endo a) where mempty = Endo id -- Instances below are listed in the same order as in https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Monoid.html instance Monoid All where mempty = All True instance Monoid Any where mempty = Any False instance Monoid Ordering where mempty = EQ instance Monoid () where mempty = () instance (Monoid a) => Monoid (Identity a) where mempty = Identity mempty instance (Consumable a) => Monoid (Monoid.First a) where mempty = Monoid.First Nothing instance (Consumable a) => Monoid (Monoid.Last a) where mempty = Monoid.Last Nothing instance (Monoid a) => Monoid (Down a) where mempty = Down mempty -- Cannot add instance (Ord a, Bounded a) => Monoid (Max a); would require (NonLinear.Ord a, Consumable a) -- Cannot add instance (Ord a, Bounded a) => Monoid (Min a); would require (NonLinear.Ord a, Consumable a) instance (Monoid a) => Monoid (Dual a) where mempty = Dual mempty instance Monoid (Endo a) where mempty = Endo id -- See Data.Num.Linear for instance ... => Monoid (Product a) -- See Data.Num.Linear for instance ... => Monoid (Sum a) -- See System.IO.Linear for instance ... => Monoid (IO a) -- See System.IO.Resource.Internal for instance ... => Monoid (RIO a) instance (Semigroup a) => Monoid (Maybe a) where mempty = Nothing -- See Data.List.Linear for instance ... => Monoid [a] -- Cannot add instance Monoid a => Monoid (Op a b); would require Dupable b instance Monoid (Proxy a) where mempty = Proxy -- Cannot add instance Monoid a => Monoid (ST s a); I think that it would require a linear ST monad -- Cannot add instance Monoid b => Monoid (a -> b); would require Dupable a instance (Monoid a, Monoid b) => Monoid (a, b) where mempty = (mempty, mempty) instance (Monoid a) => Monoid (Const a b) where mempty = mempty -- See Data.Functor.Linear.Applicative for instance ... => Monoid (Ap f a) -- Cannot add instance Alternative f => Monoid (Alt f a); we don't have a linear Alternative instance (Monoid a, Monoid b, Monoid c) => Monoid (a, b, c) where mempty = (mempty, mempty, mempty) instance (Monoid (f a), Monoid (g a)) => Monoid (Functor.Product f g a) where mempty = Pair mempty mempty instance (Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (a, b, c, d) where mempty = (mempty, mempty, mempty, mempty) instance (Monoid (f (g a))) => Monoid (Functor.Compose f g a) where mempty = Compose mempty instance (Monoid a, Monoid b, Monoid c, Monoid d, Monoid e) => Monoid (a, b, c, d, e) where mempty = (mempty, mempty, mempty, mempty, mempty) -- | Useful to treat /unrestricted/ monoids as linear ones. instance (Prelude.Monoid a) => Monoid (Ur.Ur a) where mempty = Ur.Ur Prelude.mempty {-# INLINE mempty #-}