module Reactive.Banana.Bunch.Combinators ( Event, Behavior, MonadMoment(liftMoment), apply, (<@>), union, filterE, filterJust, accumB, accumE, mapAccum, stepper, RB.valueBLater, collect, spill, ) where import qualified Reactive.Banana.Combinators as RB import Reactive.Banana.Bunch.Private (Event(Event)) import Reactive.Banana.Combinators (MonadMoment, Behavior) import Control.Monad (liftM, join) import Control.Applicative ((<$>)) import qualified Data.NonEmpty.Class as NonEmptyC import qualified Data.NonEmpty as NonEmpty import qualified Data.Traversable as Trav import Data.Maybe (catMaybes) import Data.Tuple.HT (swap, mapFst) infixl 4 <@> (<@>), apply :: Behavior (a -> b) -> Event a -> Event b (<@>) = apply apply fs (Event ass) = Event $ fmap <$> fs RB.<@> ass union :: Event a -> Event a -> Event a union (Event xs) (Event ys) = Event $ RB.unionWith NonEmptyC.append xs ys filterE :: (a -> Bool) -> Event a -> Event a filterE = filterGen . filter filterJust :: Event (Maybe a) -> Event a filterJust = filterGen catMaybes filterGen :: ([a] -> [b]) -> Event a -> Event b filterGen f (Event xs) = Event $ RB.filterJust $ fmap (NonEmpty.fetch . f . NonEmpty.flatten) xs stepper :: MonadMoment m => a -> Event a -> m (Behavior a) stepper a (Event as) = RB.stepper a $ NonEmpty.last <$> as accumE :: MonadMoment m => a -> Event (a -> a) -> m (Event a) accumE acc (Event fss) = liftM (Event . fst) $ mapAccumGen double acc fss accumB :: MonadMoment m => a -> Event (a -> a) -> m (Behavior a) accumB acc (Event fss) = liftM snd $ mapAccumGen double acc fss double :: a -> (a,a) double a = (a,a) mapAccum :: MonadMoment m => acc -> Event (acc -> (x, acc)) -> m (Event x, Behavior acc) mapAccum acc (Event fss) = liftM (mapFst Event) $ mapAccumGen swap acc fss mapAccumGen :: (MonadMoment m, Trav.Traversable t) => (s -> (acc, a)) -> acc -> RB.Event (t (acc -> s)) -> m (RB.Event (t a), Behavior acc) mapAccumGen g acc = RB.mapAccum acc . fmap (\fs a -> swap $ Trav.mapAccumL (\a0 f -> g $ f a0) a fs) collect :: Event a -> Event (NonEmpty.T [] a) collect (Event as) = Event (NonEmpty.singleton <$> as) spill :: Event (NonEmpty.T [] a) -> Event a spill (Event as) = Event (join <$> as)