# LANGUAGE GADTs , FlexibleInstances , MultiParamTypeClasses #

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Monoid.Categorical
  Copyright    :   ( c )   2009
-- License     :  BSD-style
-- Maintainer  :  
-- Stability   :  experimental
-- Portability :  portable
--
-----------------------------------------------------------------------------

module Data.Monoid.Categorical
    ( module Data.Monoid.Reducer
    , module Control.Category
    -- * Generalized Endo
    , GEndo(GEndo, getGEndo)
  *  as Categories
    , CMonoid
    , categoryToMonoid
    , monoidToCategory
    ) where

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

-- | The 'Monoid' of the endomorphisms over some object in an arbitrary 'Category'.
data GEndo k a = GEndo { getGEndo :: k a a } 

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

  | A ' Monoid ' is just a ' Category ' with one object . This fakes that with a GADT
data CMonoid m n o where
    M :: Monoid m => m -> CMonoid m a a

-- | Extract the 'Monoid' from its representation as a 'Category'
categoryToMonoid :: CMonoid m m m -> m 
categoryToMonoid (M m) = m
# INLINE categoryToMonoid #

-- | Convert a value in a 'Monoid' into an arrow in a 'Category'.
monoidToCategory :: Monoid m => m -> CMonoid m m m 
monoidToCategory = M 
# INLINE monoidToCategory #

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

instance Monoid m => Monoid (CMonoid m m m) where
    mempty = id
    mappend = (.)

instance (c `Reducer` m) => Reducer c (CMonoid m m m) where
    unit = M . unit

instance Monoid m => Reducer (CMonoid m m m) m where
    unit (M m) = m 

---------------------------------------------------------------------------
 |
 Module      :  Data.Monoid.Categorical
 License     :  BSD-style
 Maintainer  :  
 Stability   :  experimental
 Portability :  portable

---------------------------------------------------------------------------
 * Generalized Endo
 | The 'Monoid' of the endomorphisms over some object in an arbitrary 'Category'.
 | Extract the 'Monoid' from its representation as a 'Category'
 | Convert a value in a 'Monoid' into an arrow in a 'Category'.
# LANGUAGE GADTs , FlexibleInstances , MultiParamTypeClasses #

  Copyright    :   ( c )   2009

module Data.Monoid.Categorical
    ( module Data.Monoid.Reducer
    , module Control.Category
    , GEndo(GEndo, getGEndo)
  *  as Categories
    , CMonoid
    , categoryToMonoid
    , monoidToCategory
    ) where

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

data GEndo k a = GEndo { getGEndo :: k a a } 

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

  | A ' Monoid ' is just a ' Category ' with one object . This fakes that with a GADT
data CMonoid m n o where
    M :: Monoid m => m -> CMonoid m a a

categoryToMonoid :: CMonoid m m m -> m 
categoryToMonoid (M m) = m
# INLINE categoryToMonoid #

monoidToCategory :: Monoid m => m -> CMonoid m m m 
monoidToCategory = M 
# INLINE monoidToCategory #

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

instance Monoid m => Monoid (CMonoid m m m) where
    mempty = id
    mappend = (.)

instance (c `Reducer` m) => Reducer c (CMonoid m m m) where
    unit = M . unit

instance Monoid m => Reducer (CMonoid m m m) m where
    unit (M m) = m 
