-- basic reactive functions that could as well be in reactive-banana
module Reactive.Banana.ALSA.Utility where

import qualified Reactive.Banana.Combinators as RB

import qualified Control.Monad.Trans.State as MS

import Prelude hiding (sequence, )


partition ::
   (a -> Bool) -> RB.Event f a -> (RB.Event f a, RB.Event f a)
partition p =
   (\x ->
      (fmap snd $ RB.filterE fst x,
       fmap snd $ RB.filterE (not . fst) x)) .
   fmap (\a -> (p a, a))

mapMaybe ::
   (a -> Maybe b) -> RB.Event f a -> RB.Event f b
mapMaybe f = RB.filterJust . fmap f

partitionMaybe ::
   (a -> Maybe b) -> RB.Event f a -> (RB.Event f b, RB.Event f a)
partitionMaybe f =
   (\x ->
      (mapMaybe fst x,
       mapMaybe (\(mb,a) -> maybe (Just a) (const Nothing) mb) x)) .
   fmap (\a -> (f a, a))

bypass ::
   (a -> Maybe b) ->
   (RB.Event f a -> RB.Event f c) ->
   (RB.Event f b -> RB.Event f c) ->
   RB.Event f a -> RB.Event f c
bypass p fa fb evs =
   let (eb,ea) = partitionMaybe p evs
   in  RB.union (fb eb) (fa ea)

traverse ::
   s -> (a -> MS.State s b) -> RB.Event f a ->
   (RB.Event f b, RB.Behavior f s)
traverse s f = sequence s . fmap f

sequence ::
   s -> RB.Event f (MS.State s a) ->
   (RB.Event f a, RB.Behavior f s)
sequence s =
   RB.mapAccum s . fmap MS.runState