{-# LANGUAGE GADTs #-}
module Data.Monoid.Categorical
    ( module Data.Monoid
    , Endo(Endo, getEndo)
    , Mon(Mon)
    , runMon
    ) where

import Prelude hiding ((.),id)
import Data.Monoid (Monoid, mempty, mappend) 
import Control.Category

-- | The 'Monoid' of endomorphisms over some object in an arbitrary 'Category'
data Endo k a = Endo { getEndo :: k a a } 

instance Category k =>  Monoid (Endo k a) where
    mempty = Endo id
    Endo f `mappend` Endo g = Endo (f . g)

-- | A 'Monoid' is just a 'Category' with one object. 
data Mon m n o where
    Mon :: Monoid m => m -> Mon m a a

runMon :: Mon m m m -> m 
runMon (Mon m) = m

instance Monoid m => Category (Mon m) where
    id = Mon mempty
    Mon a . Mon b = Mon (a `mappend` b)