{-# 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