{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TupleSections #-}
module Data.Monoid.SemiDirectProduct
( Semi, unSemi, tag, inject, untag, embed, quotient
) where
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid (Monoid(..))
#endif
import Data.Semigroup (Semigroup(..))
import Data.Monoid.Action
newtype Semi s m = Semi { Semi s m -> (s, m)
unSemi :: (s,m) }
instance (Semigroup m, Semigroup s, Action m s) => Semigroup (Semi s m) where
Semi s m
x <> :: Semi s m -> Semi s m -> Semi s m
<> Semi s m
y = (s, m) -> Semi s m
forall s m. (s, m) -> Semi s m
Semi (s
xs s -> s -> s
forall a. Semigroup a => a -> a -> a
<> (m
xm m -> s -> s
forall m s. Action m s => m -> s -> s
`act` s
ys), m
xm m -> m -> m
forall a. Semigroup a => a -> a -> a
<> m
ym)
where (s
xs, m
xm) = Semi s m -> (s, m)
forall s m. Semi s m -> (s, m)
unSemi Semi s m
x
(s
ys, m
ym) = Semi s m -> (s, m)
forall s m. Semi s m -> (s, m)
unSemi Semi s m
y
{-# INLINE (<>) #-}
#if MIN_VERSION_base(4,8,0)
sconcat :: NonEmpty (Semi s m) -> Semi s m
sconcat = (Semi s m -> Semi s m -> Semi s m)
-> NonEmpty (Semi s m) -> Semi s m
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Semi s m -> Semi s m -> Semi s m
forall a. Semigroup a => a -> a -> a
(<>)
{-# INLINE sconcat #-}
#endif
instance (Monoid m, Monoid s, Action m s) => Monoid (Semi s m) where
mempty :: Semi s m
mempty = (s, m) -> Semi s m
forall s m. (s, m) -> Semi s m
Semi (s
forall a. Monoid a => a
mempty, m
forall a. Monoid a => a
mempty)
{-# INLINE mempty #-}
#if !MIN_VERSION_base(4,11,0)
mappend x y = Semi (xs `mappend` (xm `act` ys), xm `mappend` ym)
where (xs, xm) = unSemi x
(ys, ym) = unSemi y
{-# INLINE mappend #-}
#endif
mconcat :: [Semi s m] -> Semi s m
mconcat = (Semi s m -> Semi s m -> Semi s m)
-> Semi s m -> [Semi s m] -> Semi s m
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Semi s m -> Semi s m -> Semi s m
forall a. Monoid a => a -> a -> a
mappend Semi s m
forall a. Monoid a => a
mempty
{-# INLINE mconcat #-}
tag :: s -> m -> Semi s m
tag :: s -> m -> Semi s m
tag s
s m
m = (s, m) -> Semi s m
forall s m. (s, m) -> Semi s m
Semi (s
s,m
m)
inject :: Monoid m => s -> Semi s m
inject :: s -> Semi s m
inject = (s, m) -> Semi s m
forall s m. (s, m) -> Semi s m
Semi ((s, m) -> Semi s m) -> (s -> (s, m)) -> s -> Semi s m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,m
forall a. Monoid a => a
mempty)
untag :: Semi s m -> s
untag :: Semi s m -> s
untag = (s, m) -> s
forall a b. (a, b) -> a
fst ((s, m) -> s) -> (Semi s m -> (s, m)) -> Semi s m -> s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Semi s m -> (s, m)
forall s m. Semi s m -> (s, m)
unSemi
embed :: Monoid s => m -> Semi s m
embed :: m -> Semi s m
embed = (s, m) -> Semi s m
forall s m. (s, m) -> Semi s m
Semi ((s, m) -> Semi s m) -> (m -> (s, m)) -> m -> Semi s m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (s
forall a. Monoid a => a
mempty,)
quotient :: Semi s m -> m
quotient :: Semi s m -> m
quotient = (s, m) -> m
forall a b. (a, b) -> b
snd ((s, m) -> m) -> (Semi s m -> (s, m)) -> Semi s m -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Semi s m -> (s, m)
forall s m. Semi s m -> (s, m)
unSemi