module Control.Monad.Trans.Order.Strict ( -- * The Order monad Order, evalOrder, evalOrderWith, -- * The OrderT monad transformer OrderT, evalOrderT, evalOrderTWith, force, -- * Elements newMinimum, newMaximum, newAfter, newBefore, -- * Converting between lazy and strict OrderT lazyToStrictOrderT, strictToLazyOrderT ) where -- Control import Control.Monad import Control.Applicative import Control.Monad.Trans.Class import Control.Monad.IO.Class import qualified Control.Monad.Trans.State.Lazy as Lazy import Control.Monad.Trans.State.Strict import qualified Control.Monad.Trans.Order.Lazy as Lazy import qualified Control.Monad.Trans.Order.Lazy.Type as Lazy -- Data import Data.Functor.Identity import Data.Order.Algorithm import Data.Order.Algorithm.Type import Data.Order.Internals (OrderRep, localOrderRep, Element) -- * The Order monad type Order o = OrderT o Identity evalOrder :: (forall o . Order o a) -> a evalOrder order = runIdentity (evalOrderT order) evalOrderWith :: Algorithm -> (forall o . Order o a) -> a evalOrderWith alg order = runIdentity (evalOrderTWith alg order) -- * The OrderT monad transformer newtype OrderT o m a = OrderT (StateT (OrderRep o) m a) deriving ( Functor, Applicative, Alternative, Monad, MonadPlus, MonadTrans, MonadIO) -- FIXME: Should we also have a MonadFix instance? evalOrderT :: Monad m => (forall o . OrderT o m a) -> m a evalOrderT = evalOrderTWith defaultAlgorithm evalOrderTWith :: Monad m => Algorithm -> (forall o . OrderT o m a) -> m a evalOrderTWith (Algorithm rawAlg) (OrderT stateT) = monad where monad = evalStateT stateT (localOrderRep rawAlg) force :: Monad m => OrderT o m () force = lazyToStrictOrderT Lazy.force -- * Elements newMinimum :: Monad m => OrderT o m (Element o) newMinimum = lazyToStrictOrderT Lazy.newMinimum newMaximum :: Monad m => OrderT o m (Element o) newMaximum = lazyToStrictOrderT Lazy.newMaximum newAfter :: Monad m => Element o -> OrderT o m (Element o) newAfter elem = lazyToStrictOrderT (Lazy.newAfter elem) newBefore :: Monad m => Element o -> OrderT o m (Element o) newBefore elem = lazyToStrictOrderT (Lazy.newBefore elem) -- * Converting between lazy and strict OrderT lazyToStrictOrderT :: Lazy.OrderT o m a -> OrderT o m a lazyToStrictOrderT (Lazy.OrderT (Lazy.StateT fun)) = OrderT (StateT fun) strictToLazyOrderT :: OrderT o m a -> Lazy.OrderT o m a strictToLazyOrderT (OrderT (StateT fun)) = Lazy.OrderT (Lazy.StateT fun)