{-# LANGUAGE TypeFamilies #-} {-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.Basis.TraceGraphic -- Copyright : (c) Stephen Tetley 2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com -- Stability : unstable -- Portability : GHC -- -- Build multi-part Graphics with an accumulator (i.e. a Writer -- monad). -- -- Note - the run functions for the transformer and the plain -- monad are quite different. This is mandated by the need to -- single-thread the DrawingContext through the transformer. -- -------------------------------------------------------------------------------- module Wumpus.Drawing.Basis.TraceGraphic ( TraceGraphic , TraceGraphicT , TraceGraphicM(..) , runTraceGraphic , runTraceGraphicT , liftTraceGraphicT ) where import Wumpus.Basic.Kernel -- package: wumpus-basic import Control.Applicative import Data.Monoid newtype TraceGraphic u a = TraceGraphic { getTraceGraphic :: DrawingContext -> (a, CatPrim) } newtype TraceGraphicT u m a = TraceGraphicT { getTraceGraphicT :: DrawingContext -> m (a, CatPrim) } type instance MonUnit (TraceGraphic u a) = u type instance MonUnit (TraceGraphicT u m a) = u -- Functor instance Functor (TraceGraphic u) where fmap f ma = TraceGraphic $ \ctx -> let (a,w1) = getTraceGraphic ma ctx in (f a,w1) instance Monad m => Functor (TraceGraphicT u m) where fmap f ma = TraceGraphicT $ \ctx -> getTraceGraphicT ma ctx >>= \(a,w1) -> return (f a,w1) -- Applicative instance Applicative (TraceGraphic u) where pure a = TraceGraphic $ \_ -> (a, mempty) mf <*> ma = TraceGraphic $ \ctx -> let (f,w1) = getTraceGraphic mf ctx (a,w2) = getTraceGraphic ma ctx in (f a,w1 `mappend` w2) instance Monad m => Applicative (TraceGraphicT u m) where pure a = TraceGraphicT $ \_ -> return (a, mempty) mf <*> ma = TraceGraphicT $ \ctx -> getTraceGraphicT mf ctx >>= \(f,w1) -> getTraceGraphicT ma ctx >>= \(a,w2) -> return (f a,w1 `mappend` w2) -- Monad instance Monad (TraceGraphic u) where return a = TraceGraphic $ \_ -> (a, mempty) ma >>= k = TraceGraphic $ \ctx -> let (a,w1) = getTraceGraphic ma ctx (b,w2) = (getTraceGraphic . k) a ctx in (b, w1 `mappend` w2) instance Monad m => Monad (TraceGraphicT u m) where return a = TraceGraphicT $ \_ -> return (a, mempty) ma >>= k = TraceGraphicT $ \ctx -> getTraceGraphicT ma ctx >>= \(a,w1) -> (getTraceGraphicT . k) a ctx >>= \(b,w2) -> return (b, w1 `mappend` w2) -- DrawingCtxM instance DrawingCtxM (TraceGraphic u) where askDC = TraceGraphic $ \ctx -> (ctx, mempty) asksDC f = TraceGraphic $ \ctx -> (f ctx, mempty) localize upd ma = TraceGraphic $ \ctx -> getTraceGraphic ma (upd ctx) instance Monad m => DrawingCtxM (TraceGraphicT u m) where askDC = TraceGraphicT $ \ctx -> return (ctx, mempty) asksDC f = TraceGraphicT $ \ctx -> return (f ctx, mempty) localize upd ma = TraceGraphicT $ \ctx -> getTraceGraphicT ma (upd ctx) -- TraceGraphicM class Monad m => TraceGraphicM m where tellImage :: MonUnit (m ()) ~ u => Image u a -> m a tellImage_ :: MonUnit (m ()) ~ u => Image u a -> m () tellImage_ ma = tellImage ma >> return () instance TraceGraphicM (TraceGraphic u) where tellImage img = TraceGraphic $ \ctx -> let (PrimW o a) = runImage ctx img in (a,o) tellImage_ img = TraceGraphic $ \ctx -> let (PrimW o _) = runImage ctx img in ((),o) instance Monad m => TraceGraphicM (TraceGraphicT u m) where tellImage img = TraceGraphicT $ \ctx -> let (PrimW o a) = runImage ctx img in return (a,o) tellImage_ img = TraceGraphicT $ \ctx -> let (PrimW o _) = runImage ctx img in return ((),o) runTraceGraphic :: TraceGraphic u a -> Image u a runTraceGraphic mf = askDC >>= \ctx -> let (a,o) = getTraceGraphic mf ctx in replaceAns a $ primGraphic o -- | Note - this needs DrawingContext as an explicit parameter, -- and hence it returns a pair of @(a, HPrim u)@ rather than an -- Image. -- -- It is expected this will be wrapped in to form a specific -- TraceDrawing /draw/ function for the amalgamated monad. -- runTraceGraphicT :: Monad m => DrawingContext -> TraceGraphicT u m a -> m (a, HPrim u) runTraceGraphicT ctx mf = getTraceGraphicT mf ctx >>= \(a,o) -> return (a, singleH o) liftTraceGraphicT :: Monad m => m a -> TraceGraphicT u m a liftTraceGraphicT ma = TraceGraphicT $ \_ -> ma >>= \a -> return (a,mempty)