{-# 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 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 Monoid 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)