wires-0.2.0: Control/Wire/Utils.hs
-- |
-- Copyright: (c) 2017 Ertugrul Söylemez
-- License: BSD3
-- Maintainer: Ertugrul Söylemez <esz@posteo.de>
-- Stability: experimental
module Control.Wire.Utils
( -- * Wire utilities
withM_,
-- * Event utilities
filterE,
scan,
scan',
scanE,
splitE,
unalignE,
unlessE
)
where
import Control.Category
import Control.Wire.Core
import Control.Wire.Internal
import Data.Align
import Data.Profunctor
import Data.These
import Prelude hiding ((.), id)
-- | Filter event occurrences using the given function.
filterE :: (a -> Bool) -> Event a -> Event a
filterE p = catMapE (\x -> if p x then Just x else Nothing)
-- | Left scan and hold of the given event.
scan :: (Monad m) => a -> Wire m (Event (a -> a)) a
scan x0 = hold x0 . scanE x0
-- | Left scan and hold of the given event. The value switch occurs
-- instantly.
scan' :: (Monad m) => a -> Wire m (Event (a -> a)) a
scan' x0 = hold' x0 . scanE x0
-- | Left scan of the given event.
scanE :: (Applicative m) => a -> Wire m (Event (a -> a)) (Event a)
scanE = lmap (fmap $ \f x -> let y = f x in (y, y)) . unfoldE
-- | Split the given event
splitE :: Event (Either a b) -> (Event a, Event b)
splitE NotNow = (NotNow, NotNow)
splitE (Now (Left x)) = (Now x, NotNow)
splitE (Now (Right y)) = (NotNow, Now y)
-- | Split the given event
--
-- Inverse of 'align'.
unalignE :: Event (These a b) -> (Event a, Event b)
unalignE NotNow = (NotNow, NotNow)
unalignE (Now (This x)) = (Now x, NotNow)
unalignE (Now (That y)) = (NotNow, Now y)
unalignE (Now (These x y)) = (Now x, Now y)
-- | Event difference: like the left event, but only when the right
-- event doesn't occur at the same time.
unlessE :: Event a -> Event b -> Event a
unlessE mx my = catMapE justThis (align mx my)
-- | Run the given action to initialise the given wire. Simplified
-- variant of 'withM'. Example:
--
-- > withM_ (scan f) action
withM_ :: (Monad m) => (s -> Wire m a b) -> m s -> Wire m a b
withM_ w c = withM w (const c)