{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TypeFamilies #-} module Data.Monoids (module Data.Monoids, module X) where import Prelude hiding (Monoid, mempty, mconcat) import GHC.Exts (Constraint) import qualified Data.Monoid as M import Data.Semigroup as X (Semigroup, (<>), sconcat, stimes) import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map import qualified Data.Foldable as Foldable -------------------- -- === Mempty === -- -------------------- -- === Definition === -- class Mempty a where mempty :: a default mempty :: M.Monoid a => a mempty = M.mempty ; {-# INLINE mempty #-} instance {-# OVERLAPPABLE #-} M.Monoid a => Mempty a -- === Utils === -- type family Mempties lst :: Constraint where Mempties '[] = () Mempties (a ': as) = (Mempty a, Mempties as) ----------------------- -- === Semigroup === -- ----------------------- -- === Utils === -- mappend :: Semigroup a => a -> a -> a mappend = (<>) ; {-# INLINE mappend #-} mappendWith :: Semigroup a => a -> a -> a -> a mappendWith m l r = l <> m <> r ; {-# INLINE mappendWith #-} mappendBetween :: Semigroup a => a -> a -> a -> a mappendBetween l r m = l <> m <> r ; {-# INLINE mappendBetween #-} type family Semigroups lst :: Constraint where Semigroups '[] = () Semigroups (a ': as) = (Semigroup a, Semigroups as) -------------------- -- === Monoid === -- -------------------- -- === Definition === -- class (Mempty a, Semigroup a) => Monoid a where mconcat :: [a] -> a mconcat = foldr (<>) mempty ; {-# INLINE mconcat #-} instance {-# OVERLAPPABLE #-} (Mempty a, Semigroup a) => Monoid a -- === Utils === -- mconcat' :: (Foldable t, Monoid a) => t a -> a mconcat' = foldr (<>) mempty ; {-# INLINE mconcat' #-} intersperse :: Foldable f => a -> f a -> [a] intersperse sep a = case Foldable.toList a of [] -> [] (x:xs) -> x : prependToAll sep xs where prependToAll sep = \case [] -> [] (x:xs) -> sep : x : prependToAll sep xs {-# INLINE intersperse #-} intercalate :: (Monoid a, Foldable f) => a -> f a -> a intercalate delim l = mconcat (intersperse delim l) ; {-# INLINE intercalate #-} intercalate' :: Monoid a => a -> [a] -> a intercalate' = intercalate ; {-# INLINE intercalate' #-} -- === Instances === -- type family Monoids lst :: Constraint where Monoids '[] = () Monoids (a ': as) = (Monoid a, Monoids as) ------------------------------------ -- === Buil-in types handling === -- ------------------------------------ instance Mempty [a] where mempty = [] instance Mempty (Maybe a) where mempty = Nothing instance Mempty (Map k a) where mempty = Map.empty