wumpus-basic-0.1.1: src/Wumpus/Basic/Monads/TraceMonad.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# OPTIONS -Wall #-}
--------------------------------------------------------------------------------
-- |
-- Module : Wumpus.Basic.Monads.TraceMonad
-- Copyright : (c) Stephen Tetley 2010
-- License : BSD3
--
-- Maintainer : stephen.tetley@gmail.com
-- Stability : unstable
-- Portability : GHC
--
-- \"Trace\" monad and monad transformer.
--
-- Trace is operationally similar to the Writer monad but it
-- supports elementary consing as well as the Writer\'s monoidal
-- concatenation.
--
-- Note, some care is needed to order the output to a trace with
-- respect to the Z-order of a drawing. The API here may well
-- be too limited...
--
--------------------------------------------------------------------------------
module Wumpus.Basic.Monads.TraceMonad
(
Trace
, TraceT
, TraceM(..)
, runTrace
, runTraceT
) where
import MonadLib ( MonadT(..) ) -- package: monadLib
import Wumpus.Basic.Utils.HList
import Control.Applicative
newtype Trace i a = Trace { getTrace :: H i -> (a, H i) }
newtype TraceT i m a = TraceT { getTraceT :: H i -> m (a, H i) }
-- Functor
instance Functor (Trace i) where
fmap f m = Trace $ \w -> let (a,w') = getTrace m w in (f a, w')
instance Monad m => Functor (TraceT i m) where
fmap f m = TraceT $ \w -> getTraceT m w >>= \(a,w') ->
return (f a, w')
-- Applicative
instance Applicative (Trace i) where
pure a = Trace $ \w -> (a,w)
mf <*> ma = Trace $ \w -> let (f,w') = getTrace mf w
(a,w'') = getTrace ma w'
in (f a,w'')
instance Monad m => Applicative (TraceT i m) where
pure a = TraceT $ \w -> return (a,w)
mf <*> ma = TraceT $ \w -> getTraceT mf w >>= \(f,w') ->
getTraceT ma w' >>= \(a,w'') ->
return (f a,w'')
-- Monad
instance Monad (Trace i) where
return a = Trace $ \w -> (a,w)
m >>= k = Trace $ \w -> let (a,w') = getTrace m w
in (getTrace . k) a w'
instance Monad m => Monad (TraceT i m) where
return a = TraceT $ \w -> return (a,w)
m >>= k = TraceT $ \w -> getTraceT m w >>= \(a,w') ->
(getTraceT . k) a w' >>= \(b,w'') ->
return (b,w'')
instance MonadT (TraceT i) where
lift m = TraceT $ \w -> m >>= \ a -> return (a,w)
class TraceM m i | m -> i where
trace :: H i -> m ()
trace1 :: i -> m ()
instance TraceM (Trace i) i where
trace h = Trace $ \w -> ((), h . w)
trace1 i = Trace $ \w -> ((), i `consH` w)
instance Monad m => TraceM (TraceT i m) i where
trace h = TraceT $ \w -> return ((), h . w)
trace1 i = TraceT $ \w -> return ((), i `consH` w)
runTrace :: Trace i a -> (a,H i)
runTrace mf = getTrace mf id
runTraceT :: Monad m => TraceT i m a -> m (a,H i)
runTraceT mf = getTraceT mf id >>= \(a,w) -> return (a,w)