module Data.Monoid.Lifted
( Semigroup1(..)
, Monoid1(..)
, append1
, empty1
) where
import Control.Applicative
import Data.Functor.Compose
import Data.Functor.Identity
import Data.HashMap.Strict (HashMap)
import Data.Hashable (Hashable)
import Data.Map.Strict (Map)
import Data.Monoid
import Data.Proxy (Proxy(..))
import Data.Semigroup (Semigroup)
import Data.Functor.Const (Const(..))
import qualified Data.Functor.Product as FP
import qualified Data.HashMap.Strict as HM
import qualified Data.Map.Strict as M
import qualified Data.Semigroup as SG
class Semigroup1 f where
liftAppend :: (a -> a -> a) -> f a -> f a -> f a
append1 :: (Semigroup1 f, Semigroup a) => f a -> f a -> f a
append1 = liftAppend (SG.<>)
class Semigroup1 f => Monoid1 f where
liftEmpty :: a -> f a
empty1 :: (Monoid1 f, Monoid a) => f a
empty1 = liftEmpty mempty
instance Semigroup1 Maybe where
liftAppend _ Nothing Nothing = Nothing
liftAppend _ a@(Just _) Nothing = a
liftAppend _ Nothing a@(Just _) = a
liftAppend f (Just a) (Just b) = Just (f a b)
instance (Semigroup1 f, Semigroup1 g) => Semigroup1 (Compose f g) where
liftAppend f (Compose a) (Compose b) = Compose ((liftAppend (liftAppend f)) a b)
instance (Monoid1 f, Monoid1 g) => Monoid1 (Compose f g) where
liftEmpty a = Compose (liftEmpty (liftEmpty a))
instance Semigroup1 IO where
liftAppend = liftA2
instance Monoid1 IO where
liftEmpty = pure
instance Ord k => Semigroup1 (Map k) where
liftAppend = M.unionWith
instance Ord k => Monoid1 (Map k) where
liftEmpty _ = M.empty
instance (Hashable k, Eq k) => Semigroup1 (HashMap k) where
liftAppend = HM.unionWith
instance (Hashable k, Eq k) => Monoid1 (HashMap k) where
liftEmpty _ = HM.empty
instance Semigroup1 [] where
liftAppend _ = (++)
instance Monoid1 [] where
liftEmpty _ = []
instance Semigroup1 Identity where
liftAppend f (Identity a) (Identity b) = Identity (f a b)
instance Monoid1 Identity where
liftEmpty = Identity
instance (Semigroup1 f, Semigroup1 g) => Semigroup1 (FP.Product f g) where
liftAppend f (FP.Pair a1 b1) (FP.Pair a2 b2) = FP.Pair (liftAppend f a1 a2) (liftAppend f b1 b2)
instance (Monoid1 f, Monoid1 g) => Monoid1 (FP.Product f g) where
liftEmpty a = FP.Pair (liftEmpty a) (liftEmpty a)
instance Semigroup1 Dual where
liftAppend f (Dual a) (Dual b) = Dual (f b a)
instance Monoid1 Dual where
liftEmpty a = Dual a
instance Semigroup a => Semigroup1 ((,) a) where
liftAppend f (a1,b1) (a2,b2) = (a1 SG.<> a2, f b1 b2)
instance (Semigroup a, Monoid a) => Monoid1 ((,) a) where
liftEmpty b = (mempty,b)
instance Semigroup1 Proxy where
liftAppend _ _ _ = Proxy
instance Monoid1 Proxy where
liftEmpty _ = Proxy
instance Semigroup1 ((->) a) where
liftAppend combine f g a = combine (f a) (g a)
instance Monoid1 ((->) a) where
liftEmpty b _ = b
instance Semigroup a => Semigroup1 (Const a) where
liftAppend _ (Const x) (Const y) = Const (x SG.<> y)