module Control.Monad.Trans.Order.Lazy (
Order,
evalOrder,
evalOrderWith,
OrderT,
evalOrderT,
force,
Element,
newMinimum,
newMaximum,
newAfter,
newBefore
) where
import Control.Monad.ST
import Control.Monad.Trans.State.Lazy
import Control.Monad.Trans.Order.Raw
hiding (newMinimum, newMaximum, newAfter, newBefore)
import qualified Control.Monad.Trans.Order.Raw
as Raw
import Control.Monad.Trans.Order.Lazy.Internals
import Control.Monad.Trans.Order.Algorithm
import Control.Monad.Trans.Order.Algorithm.Type
import Data.Functor.Identity
import Data.IORef
import System.IO.Unsafe
import GHC.IORef
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)
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 (emptyOrderRep rawAlg)
force :: Monad m => OrderT o m ()
force = OrderT $ get >>= \ order -> order `seq` return ()
data Element o = Element (RawAlgorithm o RealWorld)
(Gate o)
(RawElement o RealWorld)
instance Eq (Element o) where
(==) (Element (RawAlgorithm _ _ _ _ _ _ _) _ rawElem1)
(Element _ _ rawElem2) = equal where
equal = rawElem1 == rawElem2
instance Ord (Element o) where
compare (Element rawAlg gate rawElem1)
(Element _ _ rawElem2) = ordering where
ordering = unsafePerformIO $
withRawOrder gate $ \ rawOrder ->
stToIO $ compareElements rawAlg rawOrder rawElem1 rawElem2
fromRawNew :: Monad m
=> (RawAlgorithm o RealWorld
-> RawOrder o RealWorld
-> ST RealWorld (RawElement o RealWorld))
-> OrderT o m (Element o)
fromRawNew rawNew = OrderT $ StateT (return . explicitStateNew) where
explicitStateNew order@(OrderRep rawAlg gate) = output where
output = unsafePerformIO $
withRawOrder gate $ \ rawOrder ->
do
rawElem <- stToIO $ rawNew rawAlg rawOrder
mkWeakIORef (IORef rawElem)
(withRawOrder gate $ \ rawOrder ->
stToIO $
delete rawAlg rawOrder rawElem)
return (Element rawAlg gate rawElem, order)
newMinimum :: Monad m => OrderT o m (Element o)
newMinimum = fromRawNew Raw.newMinimum
newMaximum :: Monad m => OrderT o m (Element o)
newMaximum = fromRawNew Raw.newMaximum
newAfter :: Monad m => Element o -> OrderT o m (Element o)
newAfter (~(Element _ _ rawElem)) = fromRawNeighbor Raw.newAfter rawElem
newBefore :: Monad m => Element o -> OrderT o m (Element o)
newBefore (~(Element _ _ rawElem)) = fromRawNeighbor Raw.newBefore rawElem
fromRawNeighbor :: Monad m
=> (RawAlgorithm o RealWorld
-> RawOrder o RealWorld
-> RawElement o RealWorld
-> ST RealWorld (RawElement o RealWorld))
-> RawElement o RealWorld
-> OrderT o m (Element o)
fromRawNeighbor rawNewNeighbor rawElem = fromRawNew rawNew where
rawNew rawAlg rawOrder = rawNewNeighbor rawAlg rawOrder rawElem