packages feed

reactor-0.1.3: Reactor/Observer.hs

{-# LANGUAGE DeriveDataTypeable #-}
module Reactor.Observer
  ( Observer(..)
  , (?!)
  ) where

import Prelude hiding (filter)
import Control.Monad
import Control.Exception hiding (handle)
import Control.Monad.Error
import Data.Monoid
import Data.Functor.Contravariant
import Data.Data
import Reactor.Filtered
import Reactor.Task

data Observer a = Observer 
  { (!)      :: a -> Task ()
  , handle   :: SomeException -> Task ()
  , complete :: Task ()
  } deriving Typeable

instance Contravariant Observer where
  contramap g (Observer f h c) = Observer (f . g) h c

instance Filtered Observer where
  filter p (Observer f h c) = Observer (\a -> when (p a) (f a)) h c

instance Monoid (Observer a) where
  mempty = Observer (\_ -> return ()) throwError (return ())
  p `mappend` q = Observer
    (\a -> do p ! a; q ! a)
    (\e -> do handle p e; handle q e)
    (do complete p; complete q)

-- filter and map in one operation
(?!) :: Observer b -> (a -> Maybe b) -> Observer a
Observer f h c ?! p = Observer (maybe (return ()) f . p) h c