module Control.Invertible.MonadArrow
( MonadArrow(..)
, BiKleisli
) where
import Prelude hiding (id, (.))
import Control.Category
import Control.Arrow
import Control.Monad (MonadPlus(..))
#ifdef VERSION_semigroupoids
import Data.Semigroupoid (Semigroupoid(..))
import Data.Groupoid (Groupoid(..))
#endif
import Data.Invertible.Bijection
import Control.Invertible.BiArrow
newtype MonadArrow a m b c = MonadArrow { runMonadArrow :: a (m b) (m c) }
type BiKleisli m a b = MonadArrow (<->) m a b
instance Category a => Category (MonadArrow a m) where
id = MonadArrow id
MonadArrow f . MonadArrow g = MonadArrow (f . g)
instance Monad m => Arrow (MonadArrow (->) m) where
arr = MonadArrow . arr . fmap
first (MonadArrow f) = MonadArrow (>>= \ ~(a,c) -> ( ,c) <$> f (return a))
second (MonadArrow f) = MonadArrow (>>= \ ~(a,b) -> (a, ) <$> f (return b))
MonadArrow f *** MonadArrow g = MonadArrow
(>>= \ ~(a,b) -> (,) <$> f (return a) <*> g (return b))
MonadArrow f &&& MonadArrow g = MonadArrow
(>>= \ a -> let ma = return a in (,) <$> f ma <*> g ma)
instance Monad m => ArrowChoice (MonadArrow (->) m) where
left (MonadArrow f) = MonadArrow (>>= either (fmap Left . f . return) (return . Right))
right (MonadArrow f) = MonadArrow (>>= either (return . Left) (fmap Right . f . return))
MonadArrow f +++ MonadArrow g = MonadArrow
(>>= either (fmap Left . f . return) (fmap Right . g . return))
MonadArrow f ||| MonadArrow g = MonadArrow
(>>= either (f . return) (g . return))
instance MonadPlus m => ArrowZero (MonadArrow (->) m) where
zeroArrow = MonadArrow (const mzero)
instance MonadPlus m => ArrowPlus (MonadArrow (->) m) where
MonadArrow f <+> MonadArrow g = MonadArrow (>>= \x -> let mx = return x in f mx `mplus` g mx)
liftMoA :: (MonadArrow (->) m a b -> MonadArrow (->) m c d) -> (m a -> m b) -> (m c -> m d)
liftMoA t = runMonadArrow . t . MonadArrow
liftMoA2 :: (MonadArrow (->) m a b -> MonadArrow (->) m c d -> MonadArrow (->) m e f) -> (m a -> m b) -> (m c -> m d) -> (m e -> m f)
liftMoA2 t f g = runMonadArrow (MonadArrow f `t` MonadArrow g)
instance Monad m => Arrow (MonadArrow (<->) m) where
arr = MonadArrow . arr . fmap
first (MonadArrow (f :<->: g)) = MonadArrow $ bik f :<->: bik g
where bik = liftMoA first
second (MonadArrow (f :<->: g)) = MonadArrow $ bik f :<->: bik g
where bik = liftMoA second
MonadArrow (f :<->: g) *** MonadArrow (f' :<->: g') =
MonadArrow $ bik f f' :<->: bik g g'
where bik = liftMoA2 (***)
MonadArrow (f :<->: g) &&& MonadArrow (f' :<->: _) =
MonadArrow $ liftMoA2 (&&&) f f' :<->: (g . arr (fmap fst))
instance Monad m => ArrowChoice (MonadArrow (<->) m) where
left (MonadArrow (f :<->: g)) = MonadArrow $ bik f :<->: bik g
where bik = liftMoA left
right (MonadArrow (f :<->: g)) = MonadArrow $ bik f :<->: bik g
where bik = liftMoA right
MonadArrow (f :<->: g) +++ MonadArrow (f' :<->: g') =
MonadArrow $ bik f f' :<->: bik g g'
where bik = liftMoA2 (+++)
MonadArrow (f :<->: g) ||| MonadArrow (f' :<->: _) =
MonadArrow $ liftMoA2 (|||) f f' :<->: (arr (fmap Left) . g)
instance MonadPlus m => ArrowZero (MonadArrow (<->) m) where
zeroArrow = MonadArrow (const mzero :<->: const mzero)
instance MonadPlus m => ArrowPlus (MonadArrow (<->) m) where
MonadArrow (f1 :<->: g1) <+> MonadArrow (f2 :<->: g2) =
MonadArrow $ bik f1 f2 :<->: bik g1 g2
where bik = liftMoA2 (<+>)
instance (BiArrow a, Monad m) => BiArrow (MonadArrow a m) where
f <-> g = MonadArrow (arr (fmap f) <-> arr (fmap g))
invert (MonadArrow f) = MonadArrow (invert f)
instance Monad m => BiArrow' (MonadArrow (<->) m)
#ifdef VERSION_semigroupoids
instance Semigroupoid a => Semigroupoid (MonadArrow a m) where
MonadArrow f `o` MonadArrow g = MonadArrow (f `o` g)
instance Groupoid a => Groupoid (MonadArrow a m) where
inv (MonadArrow f) = MonadArrow (inv f)
#endif