----------------------------------------------------------------------------- -- | -- Module : Control.Comonad.Context -- Copyright : 2004 Dave Menendez -- License : BSD3 -- -- Maintainer : dan.doel@gmail.com -- Stability : experimental -- Portability : portable -- -- Defines the state-in-context comonad, which is dual to the state monad. -- Each operation in the context comonad runs in a context determined -- by /later/ operations. (Observe, for example, 'experiment', which runs -- the preceeding operations multiple times in different contexts and -- returns a list of results.) -- ----------------------------------------------------------------------------- module Control.Comonad.Context ( Context(..) , get , modify , experiment , liftCtx ) where import Control.Comonad data Context c a = Context (c -> a) c instance Functor (Context c) where fmap g (Context f c) = Context (g . f) c instance Comonad (Context c) where extract (Context f c) = f c duplicate (Context f c) = Context (Context f) c -- | Returns the context get :: Context c a -> c get (Context _ c) = c -- | Returns the result of the preceeding operations running in -- a modified context modify :: (c -> c) -> Context c a -> a modify m (Context f c) = f (m c) -- | Returns a list of results created by running prior operations -- in modified contexts created by the list of context-modifiers. experiment :: [c -> c] -> Context c a -> [a] experiment ms (Context f c) = map (\m -> f (m c)) ms {-| Lifts an operation into the context comonad. Syntactic sugar for @fmap@ when chaining comonad operations. @ liftCtx == extract . fmap f w =>> liftCtx f == fmap f w @ -} liftCtx :: (a -> b) -> Context c a -> b liftCtx g (Context f c) = g (f c) {- inContext :: ((c -> a) -> c -> b) -> Context c a -> b inContext op (Context f c) = op f c get = inContext (\f c -> c) modify m = inContext (\f c -> f (m c)) -}