{-# OPTIONS_GHC -fglasgow-exts #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.Ideal -- Copyright : (C) 2008 Edward Kmett -- License : BSD-style (see the file LICENSE) -- -- Maintainer : Edward Kmett -- Stability : experimental -- Portability : portable -- ---------------------------------------------------------------------------- module Control.Monad.Ideal ( -- * Ideal Monads MonadIdeal(..) , Ideal , ideal , destroyIdeal -- * Coideal Comonads , ComonadCoideal(..) , Coideal , coideal , buildCoideal -- * Mutual recursion for (co)ideal (co)monad (co)products , Mutual(..) -- * Coideal Comonad Product , (:*) -- * Ideal Monad Coproduct , (:+) ) where import Prelude hiding (fst, snd) import Control.Category.Cartesian import Control.Category.Hask import Control.Comonad import Control.Functor import Control.Functor.Algebra import Control.Functor.Combinators.Lift import Control.Monad.Identity -- Control.Arrow ((|||),(&&&)) -- import Control.Functor.Combinators.Biff -- import Control.Functor.Combinators.Join -- import Control.Applicative type Ideal = Ap Either -- type Ideal f = Join (PFree f) type Coideal = Ap (,) -- type Coideal f = Join (PCofree f) ideal :: Either a (f a) -> Ideal f a ideal = mkAp coideal :: (a, f a) -> Coideal f a coideal = mkAp runIdeal :: Ideal f a -> Either a (f a) runIdeal = runAp runCoideal :: Coideal f a -> (a, f a) runCoideal = runAp class Functor m => MonadIdeal m where idealize :: m (Either a (m a)) -> m a instance Functor f => Pointed (Ideal f) where point = Lift . Left . Identity -- this only really needs 'ap' but there is no 'unpointed/pre- applicative' {- instance Applicative f => Applicative (Ideal f) where pure = point Ideal (Left f) <*> Ideal (Left a) = Ideal $ Left (f a) Ideal (Left f) <*> Ideal (Right bs) = Ideal $ Right (fmap f bs) Ideal (Right fs) <*> Ideal (Left a) = Ideal $ Right (fmap ($a) fs) Ideal (Right fs) <*> Ideal (Right bs) = Ideal $ Right (fs <*> bs) -} instance MonadIdeal m => Monad (Ideal m) where return = point m >>= f = ideal . (id ||| Right . idealize) . runIdeal $ fmap (runIdeal . f) m destroyIdeal :: Algebra m a -> Ideal m a -> a destroyIdeal phi = (id ||| phi) . runIdeal -- instance MonadIdeal (Fst k) where -- idealize = mkFst . runFst class Functor w => ComonadCoideal w where coidealize :: w a -> w (a, w a) instance Functor f => Copointed (Coideal f) where extract = runIdentity . fst . runLift instance ComonadCoideal w => Comonad (Coideal w) where extend f = fmap (f . coideal) . coideal . (id &&& coidealize . snd) . runCoideal buildCoideal :: Coalgebra m a -> a -> Coideal m a buildCoideal phi = coideal . (id &&& phi) -- instance ComonadCoideal (Fst k) where -- coidealize = mkFst . runFst -- * (Co)ideal (Co)products newtype Mutual p m n a = Mutual { runMutual :: m (p a (Mutual p n m a)) } type Mutual' p m n = Lift p (Mutual p m n) (Mutual p n m) type (m :+ n) = Mutual' Either m n type (m :* n) = Mutual' (,) m n instance (Bifunctor p Hask Hask Hask, Functor m, Functor n) => Functor (Mutual p m n) where fmap f = Mutual . fmap (bimap f (fmap f)) . runMutual {- instance (MonadIdeal m, MonadIdeal n) => MonadIdeal (m :+ n) where idealize = undefined -} {- instance (ComonadCoideal w, ComonadCoideal v) => ComonadCoideal (w :* v) where coidealize = undefined -}