Difference between revisions of "TypeCompose"

From HaskellWiki
Jump to navigation Jump to search
Line 15: Line 15:
   
 
== Data-driven computation ==
 
== Data-driven computation ==
  +
  +
The representation of data-driven computations is quite simple and general. They have a ''news'' publisher (<hask>news</hask>) and a source of new values (<hask>src</hask>). Clients interested in the value subscribe to <hask>news</hask> and extract a new value from <hask>src</hask> when notified that the value may have changed.
  +
  +
<haskell>
  +
type DataDrivenG news src = Compose ((,) news) src
  +
</haskell>
  +
  +
Thanks to properties of [http://darcs.haskell.org/packages/TypeCompose/doc/html/Control-Compose.html#t%3ACompose <hask>Compose</hask>], when <hask>news</hask> is a [http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Monoid.html#t%3AMonoid monoid] and <hask>src</hask> is an applicative functor, <hask>DataDriven news src</hask> is an applicative functor also. The applicative property is very convenient for composition.
  +
  +
To see how our simple definitions manage data-driven computations, expand the <hask>Applicative</hask> instances of <hask>Compose</hask> and <hask>(,) a</hask>:
  +
<haskell>
  +
instance (Applicative src) => Applicative (DataDrivenG news src) where
  +
pure a = Comp (mempty, pure a)
  +
Comp (newsf,srcf) <*> Comp (newsx, srcx) =
  +
Comp (newsf `mappend` newsx) (getf <*> getx)
  +
</haskell>
  +
  +
The idea here is that <hask>mempty</hask> is publisher that never has news to report, while <hask>mappend</hask> combines publishers into one that reports all the news of either. Thus <hask>DataDrivenG</hask> accumulates event sources as it composes, as well as delegating to whatever composition is done by <hask>src</hask>.
  +
  +
=== Specializing ===
  +
  +
Specializing, introduce types of "sinks" (consumers) of values, "updaters" (actions), and "news publishers" (somewhere to register updaters to be executed when events occur).
  +
  +
<haskell>
  +
type Sink src a = a -> Updater src
  +
type Updater src = src ()
  +
type News src = Sink src (Updater src)
  +
</haskell>
  +
  +
And specialize <hask>DataDriven</hask> for news publishers:
  +
<haskell>
  +
type DataDriven src = DataDrivenG (News src) src
  +
</haskell>
  +
  +
For instance, the "Source" types used in [[Phooey]] are defined simply as
  +
<haskell>
  +
type Source = DataDriven IO
  +
</haskell>
  +
  +
Note that <hask>News src</hask> is a [http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Monoid.html#t%3AMonoid monoid] when <hask>src ()</hask> is. In particular, given any applicative functor <hask>f</hask>, we can supply the following:
  +
<haskell>
  +
-- Standard instance: Applicative functor applied to monoid
  +
instance Monoid a => Monoid (f a) where { mempty = pure mempty; mappend = (*>) }
  +
</haskell>
  +
Note that <hask>()</hask> is a monoid. See an example in the [http://darcs.haskell.org/packages/TypeCompose/doc/html/src.Control.Instances.hs.html <hask>Control.Instances</hask> module].

Revision as of 07:29, 30 March 2007

Abstract

TypeCompose provides some classes & instances for forms of type composition. It also includes a very simple implementation of data-driven computation.

TypeCompose is used in Phooey, a functional GUI library.

Type composition

For now, see the Haddock docs.

Data-driven computation

The representation of data-driven computations is quite simple and general. They have 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.

type DataDrivenG news src = Compose ((,) news) src

Thanks to properties of Compose, 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.

To see how our simple definitions manage data-driven computations, expand the Applicative instances of Compose and (,) a:

instance (Applicative src) => Applicative (DataDrivenG news src) where
  pure a = Comp (mempty, pure a)
  Comp (newsf,srcf) <*> Comp (newsx, srcx) =
    Comp (newsf `mappend` newsx) (getf <*> getx)

The idea here is that mempty is publisher that never has news to report, while mappend combines publishers into one that reports all the news of either. Thus DataDrivenG accumulates event sources as it composes, as well as delegating to whatever composition is done by src.

Specializing

Specializing, introduce types of "sinks" (consumers) of values, "updaters" (actions), and "news publishers" (somewhere to register updaters to be executed when events occur).

type Sink src a  = a -> Updater src
type Updater src = src ()
type News src    = Sink src (Updater src)

And specialize DataDriven for news publishers:

type DataDriven src = DataDrivenG (News src) src

For instance, the "Source" types used in Phooey are defined simply as

type Source = DataDriven IO

Note that News src is a monoid when src () is. In particular, given any applicative functor f, we can supply the following:

-- Standard instance: Applicative functor applied to monoid
instance Monoid a => Monoid (f a) where { mempty = pure mempty; mappend = (*>) }

Note that () is a monoid. See an example in the Control.Instances module.