module Reactive.Bacon.Core where
import Control.Monad
import Prelude hiding (map, filter)
class Observable s where
(==>) :: s a -> (a -> IO()) -> IO ()
(>>=!) :: IO (s a) -> (a -> IO()) -> IO ()
(>>=!) action f = action >>= \observable -> (observable ==> f)
infixl 1 >>=!
data EventStream a = EventStream { subscribe :: (EventSink a -> IO Disposable) }
type EventSink a = (Event a -> IO (HandleResult))
data Event a = Next a | End
data HandleResult = More | NoMore
type Disposable = IO ()
class EventSource s where
toEventStream :: s a -> EventStream a
instance EventSource EventStream where
toEventStream = id
instance Observable EventStream where
(==>) src f = void $subscribe (toEventStream src) $toObserver f
instance Functor Event where
fmap f (Next a) = Next (f a)
fmap _ End = End
instance Show a => Show (Event a) where
show (Next x) = show x
show End = "<END>"
instance Eq a => Eq (Event a) where
(==) End End = True
(==) (Next x) (Next y) = (x==y)
(==) _ _ = False
obs :: EventSource s => s a -> EventStream a
obs = toEventStream
neverE :: EventStream a
neverE = EventStream $ \_ -> return $(return ())
toObserver :: (a -> IO()) -> EventSink a
toObserver next = sink
where sink (Next x) = next x >> return More
sink End = return NoMore
toEventObserver :: (Event a -> IO()) -> EventSink a
toEventObserver next = sink
where sink event = next event >> return More
data Property a = Property { addPropertyListener :: PropertySink a -> IO Disposable }
class PropertySource s where
toProperty :: s a -> Property a
instance PropertySource Property where
toProperty = id
data PropertyEvent a = Initial a | Update a | EndUpdate
type PropertySink a = PropertyEvent a -> IO HandleResult