free-algebras-0.0.5.0: src/Data/Monoid/MSet.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{- |
Monoid and [group actions](https://en.wikipedia.org/wiki/Group_action) (M-Sets and G-Sets).
The category of @MSet@s (and @GSet@s) is monadic (unlike the category of @SSet@s).
-}
module Data.Monoid.MSet
( MSet
, SSet (..)
, Endo (..)
, rep
, fact
, FreeMSet (..)
, hoistFreeMSet
, foldrMSet
, S (..)
) where
import Control.Monad (ap)
import Data.Functor.Const (Const (..))
import Data.Functor.Identity (Identity (..))
import qualified Data.Functor.Product as Functor (Product)
import qualified Data.Functor.Sum as Functor (Sum)
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NE
import Data.Monoid (Monoid, Endo (..), Sum (..))
import Data.Natural (Natural)
import Data.Ord (Down (..))
import Data.Semigroup (Semigroup (..))
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Semigroup.SSet (SSet (..), S (..), fact, rep)
import Data.Algebra.Free
( AlgebraType
, AlgebraType0
, FreeAlgebra (..)
, proof
, bindFree
, foldrFree
)
-- |
-- Lawful instance should satisfy:
--
-- prop> act mempty = id
-- prop> g `act` h `act` a = g <> h `act` a
--
-- This is the same as to say that `act` is a monoid homomorphism from @m@ to
-- the monoid of endomorphisms of @a@ (i.e. maps from @a@ to @a@).
--
-- Note that if @g@ is a @'Group'@ then an @MSet@ is simply a @GSet@, this
-- is because monoids and groups share the same morphisms (a monoid homomorphis
-- between groups necessarily preserves inverses).
#if __GLASGOW_HASKELL__ > 822
class (Monoid m , SSet m a) => MSet m a
mact :: m -> a -> a
mact = act
#else
class Monoid m => MSet m a where
mact :: m -> a -> a
#endif
instance Monoid m => MSet m m where
#if __GLASGOW_HASKELL__ <= 822
mact = mappend
#endif
instance (MSet m a, MSet m b) => MSet m (a, b) where
#if __GLASGOW_HASKELL__ <= 822
mact m (a, b) = (mact m a, mact m b)
#endif
instance (MSet m a, MSet m b, MSet m c) => MSet m (a, b, c) where
#if __GLASGOW_HASKELL__ <= 822
mact m (a, b, c) = (mact m a, mact m b, mact m c)
#endif
instance (MSet m a, MSet m b, MSet m c, MSet m d) => MSet m (a, b, c, d) where
#if __GLASGOW_HASKELL__ <= 822
mact m (a, b, c, d) = (mact m a, mact m b, mact m c, mact m d)
#endif
instance (MSet m a, MSet m b, MSet m c, MSet m d, MSet m e) => MSet m (a, b, c, d, e) where
#if __GLASGOW_HASKELL__ <= 822
mact m (a, b, c, d, e) = (mact m a, mact m b, mact m c, mact m d, mact m e)
#endif
instance (MSet m a, MSet m b, MSet m c, MSet m d, MSet m e, MSet m f) => MSet m (a, b, c, d, e, f) where
#if __GLASGOW_HASKELL__ <= 822
mact m (a, b, c, d, e, f) = (mact m a, mact m b, mact m c, mact m d, mact m e, mact m f)
#endif
instance (MSet m a, MSet m b, MSet m c, MSet m d, MSet m e, MSet m f, MSet m h) => MSet m (a, b, c, d, e, f, h) where
#if __GLASGOW_HASKELL__ <= 822
mact m (a, b, c, d, e, f, h) = (mact m a, mact m b, mact m c, mact m d, mact m e, mact m f, mact m h)
#endif
instance (MSet m a, MSet m b, MSet m c, MSet m d, MSet m e, MSet m f, MSet m h, MSet m i) => MSet m (a, b, c, d, e, f, h, i) where
#if __GLASGOW_HASKELL__ <= 822
mact m (a, b, c, d, e, f, h, i) = (mact m a, mact m b, mact m c, mact m d, mact m e, mact m f, mact m h, mact m i)
#endif
instance MSet m a => MSet m [a] where
#if __GLASGOW_HASKELL__ <= 822
mact m = map (mact m)
#endif
instance MSet m a => MSet m (NonEmpty a) where
#if __GLASGOW_HASKELL__ <= 822
mact m = NE.map (mact m)
#endif
instance (MSet m a, Ord a) => MSet m (Set a) where
#if __GLASGOW_HASKELL__ <= 822
mact m as = Set.map (mact m) as
#endif
{--
- instance {-# OVERLAPPABLE #-} (Functor f, MSet m a) => MSet m (f a) where
- act m fa = fmap (act m) fa
--}
#if __GLASGOW_HASKELL__ <= 822
fmact :: (Functor f, MSet s a) => s -> f a -> f a
fmact s = fmap (mact s)
#endif
instance MSet m a => MSet m (Identity a) where
#if __GLASGOW_HASKELL__ <= 822
mact = fmact
#endif
instance MSet m a => MSet (Identity m) a where
#if __GLASGOW_HASKELL__ <= 822
mact (Identity f) a = f `mact` a
#endif
instance MSet m a => MSet m (Maybe a) where
#if __GLASGOW_HASKELL__ <= 822
mact = fmact
#endif
instance MSet m b => MSet m (Either a b) where
#if __GLASGOW_HASKELL__ <= 822
mact = fmact
#endif
instance MSet m a => MSet m (Down a) where
#if __GLASGOW_HASKELL__ <= 822
mact m (Down a) = Down (mact m a)
#endif
instance MSet m a => MSet m (IO a) where
#if __GLASGOW_HASKELL__ <= 822
mact = fmact
#endif
instance MSet m b => MSet m (a -> b) where
#if __GLASGOW_HASKELL__ <= 822
mact = fmact
#endif
instance MSet (Endo a) a where
#if __GLASGOW_HASKELL__ <= 822
mact = appEndo
#endif
instance {-# OVERLAPPABLE #-} MSet m a => MSet (S m) a where
#if __GLASGOW_HASKELL__ <= 822
S m `mact` a = m `mact` a
#endif
instance {-# OVERLAPPING #-} MSet m b => MSet (S m) (Endo b) where
#if __GLASOW_HASKELL__ <= 822
mact m (Endo f) = Endo $ mact m . f
#endif
instance Monoid m => MSet (Sum Natural) m where
#if __GLASOW_HASKELL__ <= 822
mact (Sum 0) _ = mempty
mact (Sum n) s = s `mappend` mact (Sum (n - 1)) s
#endif
instance MSet m a => MSet m (Const a b) where
#if __GLASOW_HASKELL__ <= 822
mact s (Const a) = Const $ s `mact` a
#endif
instance (Functor f, Functor h, MSet m a) => MSet m (Functor.Product f h a) where
#if __GLASOW_HASKELL__ <= 822
mact = fmact
#endif
instance (Functor f, Functor h, MSet m a) => MSet m (Functor.Sum f h a) where
#if __GLASOW_HASKELL__ <= 822
mact = fmact
#endif
newtype FreeMSet m a = FreeMSet { runFreeMSet :: (m, a) }
deriving (Show, Ord, Eq, Functor)
hoistFreeMSet
:: (m -> n) -- ^ monoid homomorphism
-> FreeMSet m a
-> FreeMSet n a
hoistFreeMSet f (FreeMSet (m, a)) = FreeMSet (f m, a)
instance Monoid m => Applicative (FreeMSet m) where
pure = returnFree
(<*>) = ap
instance ( Monoid m
) => Monad (FreeMSet m) where
return = returnFree
(>>=) = bindFree
instance Semigroup m => SSet m (FreeMSet m a) where
act m (FreeMSet (h, a)) = FreeMSet (m <> h, a)
instance Monoid m => MSet m (FreeMSet m a) where
#if __GLASOW_HASKELL__ <= 822
mact m (FreeMSet (h, a)) = FreeMSet (m `mappend` h, a)
#endif
-- |
-- @'foldrFree'@ for @'FreeMSet'@
foldrMSet :: forall m a b . MSet m b => (a -> b -> b) -> b -> (m, a) -> b
foldrMSet f b (m, a) = foldrFree f b (FreeMSet (S m, a))
type instance AlgebraType0 (FreeMSet m) a = ()
type instance AlgebraType (FreeMSet m) a = MSet m a
instance ( Monoid m
) => FreeAlgebra (FreeMSet m) where
returnFree a = FreeMSet (mempty, a)
foldMapFree f (FreeMSet (m, a)) = mact m (f a)
codom = proof
forget = proof