{-# LANGUAGE UndecidableInstances,FlexibleInstances,MultiParamTypeClasses #-}
module Control.Monad.Royal where
{-

Royal Monads (or relative polymonads) generalize monads, polymonads _and_ relative monads.

Therefore Royal Monads (captalize to emphasise royalness) are the king of monads! 

The ultimate abstraction! 

Ditch your boring old (relative) (poly) monad, and start programming
with the king of monads! 

Bow before the ultimate generality of the Royal Monad, infidels!
-}

class RoyalReturn m r where
  royalReturn :: r a -> m a

class (RoyalReturn m r, RoyalReturn n r, RoyalReturn p r) => 
     RoyalMonad m n p r where
  royalBind   :: m a -> (r a -> n a) -> p a
  -- laws:
  -- royalBind m royalReturn = m
  -- royalBind (royalReturn x) f = f x 
  -- royalBind m (\x -> royalBind (f x) g) = royalBind (royalBind m f) g




class RoyalReturn m r => RelMonad m r where
  relativeBind :: m a -> (r a -> m b) -> m b
  -- laws:
  -- relativeBind m royalReturn = m
  -- relativeBind (royalReturn x) f = f x 
  -- relativeBind m (\x -> relativeBind (f x) g) = relativeBind (relativeBind m f) g

class NonRoyalReturn m where
  rreturn :: a -> m a

class (NonRoyalReturn m, NonRoyalReturn n, NonRoyalReturn p) =>
    PolyMonad m n p where
  polyBind :: m a -> (a -> n b) -> p b
  -- laws:
  -- polyBind m rreturn = m
  -- polyBind (rreturn x) f = f x 
  -- polyBind m (\x -> polyBind (f x) g) = polyBind (polyBind m f) g

newtype Id a = Id { fromId :: a} 

instance NonRoyalReturn m => RoyalReturn m Id where
  royalReturn (Id x) = rreturn x

instance PolyMonad m n p => RoyalMonad m n p Id where
  royalBind m f = polyBind m (f . Id)

instance Monad m => NonRoyalReturn m where
  rreturn = return

instance Monad m => RoyalMonad m m m Id where
  royalBind m f = m >>= (f . Id)