module Control.Monad.Trans.Order.Strict ( -- * The Order monad Order, perform, -- * The OrderT monad transformer OrderT, performT, getOrderToken, -- * Element creation newMinimum, newMaximum, newAfter, newBefore, -- * Converting between lazy and strict OrderT lazyToStrictOrderT, strictToLazyOrderT ) where -- Control import Control.Applicative import Control.Monad import Control.Monad.Fix import Control.Monad.Trans.Class (MonadTrans) import qualified Control.Monad.Trans.Class as Trans (lift) import Control.Monad.IO.Class import qualified Control.Monad.Trans.State.Strict as Strict import Control.Monad.Trans.Order.Representation (OrderTRep (OrderTRep), StateMonadTrans (..)) import qualified Control.Monad.Trans.Order.Representation as OrderTRep import qualified Control.Monad.Trans.Order.Lazy.Type as Lazy (OrderT (OrderT)) -- Data import Data.Functor.Identity import Data.Order.Pair.Type import Data.Order.Element {-FIXME: Consider introducing a restricted variant of mapStateT: mapOrderT :: (forall a . m a -> n a) -> OrderT o m a -> OrderT o n a Maybe this should not be called mapOrderT, since it is only a restricted variant and a corresponding mapOrder would be trivial. -} {-FIXME: Probably we should also have variants of liftCallCC, etc., which are present for StateT. -} -- * The Order monad type Order o = OrderT o Identity perform :: (a -> Order o b) -> OrderPair o a -> OrderPair o b perform fun pair = runIdentity (performT fun pair) -- * The OrderT monad transformer newtype OrderT o m a = OrderT { runOrderT :: OrderTRep Strict.StateT o m a } deriving ( Functor, Applicative, Alternative, Monad, MonadPlus, MonadFix, MonadTrans, MonadIO ) instance StateMonadTrans Strict.StateT where -- Construction and destruction stateT = Strict.StateT runStateT = Strict.runStateT -- Functor fmap' = fmap (<$!) = (<$) -- Applicative pure' = pure (<*>!) = (<*>) (*>!) = (*>) (<*!) = (<*) -- Alternative empty' = empty (<|>!) = (<|>) some' = some many' = many -- Monad (>>=!) = (>>=) (>>!) = (>>) return' = return fail' = fail -- MonadPlus mzero' = mzero mplus' = mplus -- MonadFix mfix' = mfix -- MonadTrans lift' = Trans.lift -- MonadIO liftIO' = liftIO performT :: Functor f => (a -> OrderT o f b) -> OrderPair o a -> f (OrderPair o b) performT fun (OrderPair (val, orderRep)) = output where output = OrderTRep.performT (runOrderT . fun) val orderRep getOrderToken :: Applicative f => OrderT o f () getOrderToken = OrderT $ OrderTRep.getOrderToken lift :: Functor f => f a -> OrderT o f a lift struct = OrderT $ OrderTRep.lift struct {-NOTE: This version is more general than the one from MonadTrans, since it works with arbitrary functors, not just monads. -} -- * Element creation newMinimum :: Applicative f => OrderT o f (Element o) newMinimum = OrderT $ OrderTRep.newMinimum newMaximum :: Applicative f => OrderT o f (Element o) newMaximum = OrderT $ OrderTRep.newMaximum newAfter :: Applicative f => Element o -> OrderT o f (Element o) newAfter elem = OrderT $ OrderTRep.newAfter elem newBefore :: Applicative f => Element o -> OrderT o f (Element o) newBefore elem = OrderT $ OrderTRep.newBefore elem -- * Converting between lazy and strict OrderT lazyToStrictOrderT :: Lazy.OrderT o m a -> OrderT o m a lazyToStrictOrderT (Lazy.OrderT (OrderTRep comp)) = strictOrderT where strictOrderT = OrderT $ OrderTRep $ stateT (runStateT comp) strictToLazyOrderT :: OrderT o m a -> Lazy.OrderT o m a strictToLazyOrderT (OrderT (OrderTRep comp)) = lazyOrderT where lazyOrderT = Lazy.OrderT $ OrderTRep $ stateT (runStateT comp)