packages feed

bludigon-0.1.1.0: src/Bludigon/Control/Concat.hs

{-# LANGUAGE QuantifiedConstraints, UndecidableInstances #-}

module Bludigon.Control.Concat (
  ControlConcatT
, runControlConcatT
, (!>)
) where

import Control.Monad.Base
import Control.Monad.Trans
import Control.Monad.Trans.Control

import Bludigon.Control

newtype ControlConcatT (t1 :: (* -> *) -> * -> *) (t2 :: (* -> *) -> * -> *) (m :: * -> *) a = ControlConcatT { unControlConcatT :: t2 (t1 m) a }
  deriving (Applicative, Functor, Monad, MonadBase b, MonadBaseControl b)

instance (forall m. Monad m => Monad (t1 m), MonadTrans t1, MonadTrans t2) => MonadTrans (ControlConcatT t1 t2) where
  lift = ControlConcatT . lift . lift

instance (forall m. Monad m => Monad (t1 m), MonadTransControl t1, MonadTransControl t2) => MonadTransControl (ControlConcatT t1 t2) where
  type StT (ControlConcatT t1 t2) a = StT t1 (StT t2 a)
  liftWith inner = ControlConcatT $
    liftWith $ \ runT2 ->
      liftWith $ \ runT1 ->
        inner $ runT1 . runT2 . unControlConcatT
  restoreT = ControlConcatT . restoreT . restoreT

instance (MonadControl (t1 m), MonadControl (t2 (t1 m)), MonadTrans t2) => MonadControl (ControlConcatT t1 t2 m) where
  type ControlConstraint (ControlConcatT t1 t2 m) a = (ControlConstraint (t1 m) a, ControlConstraint (t2 (t1 m)) a)
  doInbetween a = do ControlConcatT . lift $ doInbetween a
                     ControlConcatT $ doInbetween a

runControlConcatT :: (t1 m a -> m a) -> (t2 (t1 m) a -> t1 m a) -> ControlConcatT t1 t2 m a -> m a
runControlConcatT runT1 runT2 = runT1 . runT2 . unControlConcatT

infixr 5 !>
(!>) :: (t1 m a -> m a) -> (t2 (t1 m) a -> t1 m a) -> (ControlConcatT t1 t2 m a -> m a)
(!>) = runControlConcatT