-- | -- Module: Control.Wire.Prefab.Accum -- Copyright: (c) 2012 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez -- -- Accumulation wires. These are left-scan equivalents of several -- sorts. module Control.Wire.Prefab.Accum ( -- * General -- ** Accumulation accum, accumT, accum1, accumT1, -- ** Function iteration iterateW, iterateWT, -- ** Generic unfolding unfold, unfoldT, -- * Special countFrom, enumFromW, mconcatW ) where import Control.Wire.Wire import Data.AdditiveGroup import Data.Monoid import Prelude hiding (enumFrom, iterate) -- | The most general accumulator. This wire corresponds to a left -- scan. -- -- * Depends: previous instant. accum :: (b -> a -> b) -> b -> Wire e m a b accum f = accumT (const f) -- | Non-delaying variant of 'accum'. -- -- * Depends: current instant. accum1 :: (b -> a -> b) -> b -> Wire e m a b accum1 f = accumT1 (const f) -- | Like 'accum', but the accumulation function also receives the -- current time delta. -- -- * Depends: previous instant. accumT :: (Time -> b -> a -> b) -> b -> Wire e m a b accumT f x' = mkPure $ \dt x -> x' `seq` (Right x', accumT f (f dt x' x)) -- | Non-delaying variant of 'accumT'. -- -- * Depends: current instant. accumT1 :: (Time -> b -> a -> b) -> b -> Wire e m a b accumT1 f x' = mkPure $ \dt x -> let y = f dt x' x in y `seq` (Right y, accumT f y) -- | Counts from the given vector adding the current input for the next -- instant. -- -- * Depends: previous instant. countFrom :: (AdditiveGroup b) => b -> Wire e m b b countFrom = accum (^+^) -- | Enumerates from the given element. enumFromW :: (Enum b) => b -> Wire e m a b enumFromW = accum (\x _ -> succ x) -- | Apply the input function continously. Corresponds to 'iterate' for -- lists. iterateW :: (b -> b) -> b -> Wire e m a b iterateW f = accum (\x _ -> f x) -- | Like 'iterate', but the accumulation function also receives the -- current time delta. iterateWT :: (Time -> b -> b) -> b -> Wire e m a b iterateWT f = accumT (\dt x _ -> f dt x) -- | Running 'Monoid' sum. -- -- * Depends: previous instant. mconcatW :: (Monoid b) => Wire e m b b mconcatW = accum mappend mempty -- | Corresponds to 'unfoldr' for lists. -- -- * Depends: current instant, if the unfolding function is strict in -- its second argument. unfold :: (s -> a -> (b, s)) -> s -> Wire e m a b unfold = unfoldT . const -- | Like 'unfold', but the accumulation function also receives the -- current time delta. -- -- * Depends: current instant, if the unfolding function is strict in -- its third argument. unfoldT :: (Time -> s -> a -> (b, s)) -> s -> Wire e m a b unfoldT f s' = mkPure $ \dt x' -> let (x, s) = f dt s' x' in x `seq` (Right x, unfoldT f s)