{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE RankNTypes #-}
module Control.Monatron.Zipper where
import Control.Monatron.MonadT ()
import Control.Monatron.IdT ()
import Control.Monatron.AutoLift
import Control.Monatron.Operations
import Control.Monatron.Monad ()
newtype (t1 :> (t2 :: (* -> *) -> * -> *)) m a = L { runL :: t1 (t2 m) a }
runZipper :: (t1 :> t2) m a -> t1 (t2 m) a
runZipper = runL
zipper :: t1 (t2 m) a -> (t1 :> t2) m a
zipper = L
leftL :: (t1 :> t2) m a -> t1 (t2 m) a
leftL = runL
rightL :: t1 (t2 m) a -> (t1 :> t2) m a
rightL = L
instance (FMonadT t1, FMonadT t2) => FMonadT (t1 :> t2) where
tmap' d1 d2 g f =
L . tmap' (FunctorD (mtmap d1)) (FunctorD (mtmap d2)) g (tmap' d1 d2 id f) . runL
instance (MonadT t1, MonadT t2) => MonadT (t1 :> t2) where
lift = L . lift . lift
tbind m f = L $ runL m >>= runL . f
instance (Monad m, MonadT t1, MonadT t2, StateM z (t2 m)) => StateM z ((t1 :> t2) m) where
stateModel = L . liftAlgModel stateModel
instance (WriterM z (t2 m), MonadT t1, Monad m, MonadT t2) => WriterM z ((t1 :> t2) m) where
writerModel = L . liftAlgModel writerModel
instance (ReaderM z (t2 m), FMonadT t1, FMonadT t2, Functor (t2 m), Monad m) =>
ReaderM z ((t1 :> t2) m) where
readerModel = L . liftModel readerModel . fmap runL
instance (ExcM z (t2 m), FMonadT t1, FMonadT t2, Functor (t2 m), Monad m) =>
ExcM z ((t1 :> t2) m) where
throwModel = L . liftAlgModel throwModel
handleModel = L . liftModel handleModel . fmap runL
instance (ContM r (t2 m), FMonadT t1, FMonadT t2, Functor (t2 m), Monad m) =>
ContM r ((t1 :> t2) m) where
contModel = L . liftAlgModel contModel
instance (ListM (t2 m), FMonadT t1, FMonadT t2, Functor (t2 m), Monad m) =>
ListM ((t1 :> t2) m) where
listModel = L . liftAlgModel listModel
data (:><:) m n = View {
to :: forall a . m a -> n a,
from :: forall a . n a -> m a
}
i :: m :><: m
i = View id id
o :: (Monad m, MonadT t1, MonadT t2) => t1 (t2 m) :><: (t1 :> t2) m
o = View rightL leftL
vlift :: (FMonadT t, Functor m, Functor n)
=> (m :><: n) -> (t m :><: t n)
vlift v = View (tmap (to v)) (tmap (from v))
hcomp :: (n :><: o) -> (m :><: n) -> (m :><: o)
v2 `hcomp` v1 = View (to v2 . to v1) (from v1 . from v2)
vcomp :: (Functor m1, Functor m2, FMonadT t)
=> (t m2 :><: m3) -> (m1 :><: m2) -> (t m1 :><: m3)
v2 `vcomp` v1 = v2 `hcomp` (vlift v1)
r :: Monad m => StateT s m :><: ReaderT s m
r = View {
to = \s -> readerT (\e -> liftM fst $ runStateT e s),
from = \e -> stateT (\s -> liftM (\x -> (x,s)) $ runReaderT s e)
}
stateIso :: Monad m => (s1 -> s2) -> (s2 -> s1) -> StateT s1 m :><: StateT s2 m
stateIso f fm1 = View {to = iso f fm1, from = iso fm1 f } where
iso g h m = stateT $ \s2 -> do (a, s1) <- runStateT (h s2) m
return (a, g s1)
getv :: StateM s n => (m :><: n) -> m s
getv var = from var get
putv :: StateM s n => (m :><: n) -> s -> m ()
putv var = from var . put