TypeCompose-0.0: src/Control/DataDriven.hs
{-# OPTIONS -fglasgow-exts #-}
----------------------------------------------------------------------
-- |
-- Module : Control.DataDriven
-- Copyright : (c) Conal Elliott 2007
-- License : LGPL
--
-- Maintainer : conal@conal.net
-- Stability : experimental
-- Portability : portable
--
-- Data-driven computations
----------------------------------------------------------------------
module Control.DataDriven
(
-- * Plumbing for \"events\" and subscription
Sink, Updater, News
-- * Data-driven computations
, DataDrivenG, dd, mapSrc
, DataDriven, runDD, joinDD
) where
import Control.Applicative
import Control.Monad (join)
import Control.Arrow (second)
import Data.Monoid
import Control.Compose
{----------------------------------------------------------
Plumbing for event publishing
----------------------------------------------------------}
-- | Sinks (consumers) of values
type Sink src a = a -> Updater src
-- | Updaters (actions)
type Updater src = src ()
-- | News publisher -- somewhere to register updaters to be executed
-- when events occur.
type News src = Sink src (Updater src)
{----------------------------------------------------------
Data-driven computations
----------------------------------------------------------}
-- | The general type of data-driven computations. Represented as a
-- /news/ publisher (@news@) and a source of new values (@src@). Clients
-- interested in the value subscribe to @news@ and extract a new value
-- from @src@ when notified that the value may have changed. When @news@
-- is a monoid and @src@ is an applicative functor, @DataDriven news src@
-- is an applicative functor also. The applicative property is very
-- convenient for composition. See the more specific type 'DataDriven'.
type DataDrivenG news src = Compose ((,) news) src
-- | Construct a data-driven computation from a subscription service
-- (@Monoid@) and a value source subscriber (@Applicative@).
dd :: news -> src a -> DataDrivenG news src a
dd = curry Comp
-- | Modify the source part of a 'DataDriven' computation.
mapSrc :: (src a -> src b) -> (DataDrivenG news src a -> DataDrivenG news src b)
mapSrc f = onComp (second f)
-- | Data driven with news publisher
type DataDriven src = DataDrivenG (News src) src
-- | Run a unit-valued 'DataDriven' computation. Causes the source to be
-- executed /and/ registered with the subscriber.
runDD :: (Monoid (Updater src), Applicative src)
=> DataDriven src () -> Updater src
runDD (Comp (news,src)) = news src `mappend` src
-- | Apply 'join' to a source
joinDD :: Monad src => DataDriven src (src a) -> DataDriven src a
joinDD = mapSrc join
-- runDDJoin :: (Monad src, Applicative src, Monoid (Updater src))
-- => DataDriven src (Updater src) -> Updater src
-- runDDJoin = runDD . joinDD