category-extras-0.2: Control/Comonad/Context.hs
-----------------------------------------------------------------------------
-- |
-- 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))
-}