module Control.Functor.Algebra
( Dialgebra, GDialgebra
, Bialgebra, GBialgebra
, Algebra, GAlgebra
, Coalgebra, GCoalgebra
, liftAlgebra
, liftCoalgebra
, liftDialgebra
, fromCoalgebra
, fromAlgebra
, fromBialgebra
) where
import Control.Comonad
import Control.Monad.Identity
import Control.Functor
import Control.Functor.Extras
import Control.Functor.Combinators.Lift
type Dialgebra f g a = f a -> g a
type GDialgebra f g w m a = f (w a) -> g (m a)
type Bialgebra f g a = (Algebra f a, Coalgebra g a)
type GBialgebra f g w m a = (GAlgebra f w a, GCoalgebra g m a)
type Algebra f a = f a -> a
type Coalgebra f a = a -> f a
type GAlgebra f w a = f (w a) -> a
type GCoalgebra f m a = a -> f (m a)
liftAlgebra :: (Functor f, Comonad w) => Algebra f :~> GAlgebra f w
liftAlgebra phi = phi . fmap extract
liftCoalgebra :: (Functor f, Monad m) => Coalgebra f :~> GCoalgebra f m
liftCoalgebra psi = fmap return . psi
liftDialgebra :: (Functor g, Functor f, Comonad w, Monad m) => Dialgebra f g :~> GDialgebra f g w m
liftDialgebra phi = fmap return . phi . fmap extract
fromAlgebra :: Algebra f :~> Dialgebra f Identity
fromAlgebra phi = Identity . phi
fromCoalgebra :: Coalgebra f :~> Dialgebra Identity f
fromCoalgebra psi = psi . runIdentity
fromBialgebra :: Bialgebra f g :~> Dialgebra (f :*: Identity) (Identity :*: g)
fromBialgebra (phi,psi) = Lift . bimap (Identity . phi) (psi . runIdentity) . runLift