varying 0.1.1.1 → 0.1.1.2
raw patch · 7 files changed
+73/−67 lines, 7 filesdep ~base
Dependency ranges changed: base
Files
- README.md +3/−0
- src/Control/Varying/Core.hs +8/−8
- src/Control/Varying/Event.hs +41/−41
- src/Control/Varying/Time.hs +5/−4
- src/Control/Varying/Tween.hs +10/−9
- src/Example.hs +3/−2
- varying.cabal +3/−3
README.md view
@@ -1,4 +1,7 @@ # varying++[](https://travis-ci.org/schell/varying)+ This library provides automaton based varying values useful for both functional reactive programming (FRP) and locally stateful programming (LSP). It is influenced by the [netwire](http://hackage.haskell.org/package/netwire) and
src/Control/Varying/Core.hs view
@@ -109,7 +109,7 @@ execVar v a = snd <$> (runVar v a) -- | Loop over a 'Var' that takes no input value.-loopVar_ :: Monad m => Var m () a -> m ()+loopVar_ :: (Functor m, Monad m) => Var m () a -> m () loopVar_ v = execVar v () >>= loopVar_ -- | Loop over a 'Var' that produces its own next input value.@@ -219,7 +219,7 @@ -- -- > fmap (*3) $ accumulate (+) 0 -- Will sum input values and then multiply the sum by 3.-instance Monad m => Functor (Var m b) where+instance (Applicative m, Monad m) => Functor (Var m b) where fmap f' v = v ~> var f' -- | A very simple category instance.@@ -234,14 +234,14 @@ -- -- It is preferable for consistency (and readability) to use 'plug left' ('<~') -- and 'plug right' ('~>') instead of ('.') where possible.-instance Monad m => Category (Var m) where+instance (Applicative m, Monad m) => Category (Var m) where id = var id f . g = g ~> f -- | 'Var's are applicative. -- -- > (,) <$> pure True <*> var "Applicative"-instance Monad m => Applicative (Var m a) where+instance (Applicative m, Monad m) => Applicative (Var m a) where pure = var . const vf <*> va = Var $ \a -> do (f, vf') <- runVar vf a (b, va') <- runVar va a@@ -258,7 +258,7 @@ -- which is equivalent to -- -- > v = (\ex ey -> (+) <$> ex <*> ey) <$> intEventVar <*> anotherIntEventVar-instance Monad m => Arrow (Var m) where+instance (Applicative m, Monad m) => Arrow (Var m) where arr = var first v = Var $ \(b,d) -> do (c, v') <- runVar v b return $ ((c,d), first v')@@ -267,7 +267,7 @@ -- -- > let v = 1 ~> accumulate (+) 0 -- which will sum the natural numbers.-instance (Monad m, Num b) => Num (Var m a b) where+instance (Applicative m, Monad m, Num b) => Num (Var m a b) where (+) = liftA2 (+) (-) = liftA2 (-) (*) = liftA2 (*)@@ -279,7 +279,7 @@ -- -- > let v = pi ~> accumulate (*) 0.0 -- which will attempt (and succeed) to multiply pi by zero every step.-instance (Monad m, Floating b) => Floating (Var m a b) where+instance (Applicative m, Monad m, Floating b) => Floating (Var m a b) where pi = pure pi exp = fmap exp log = fmap log@@ -291,7 +291,7 @@ -- -- > let v = 2.5 ~> accumulate (+) 0 -- which will add 2.5 each step.-instance (Monad m, Fractional b) => Fractional (Var m a b) where+instance (Applicative m, Monad m, Fractional b) => Fractional (Var m a b) where (/) = liftA2 (/) fromRational = pure . fromRational --------------------------------------------------------------------------------
src/Control/Varying/Event.hs view
@@ -11,9 +11,6 @@ -- -- You can use 'Event' just like you would 'Maybe'. ---{-# LANGUAGE Arrows #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE PartialTypeSignatures #-} module Control.Varying.Event ( Event(..), -- * Transforming event values.@@ -66,8 +63,8 @@ import Prelude hiding (until) import Control.Varying.Core import Control.Applicative-import Control.Arrow import Control.Monad+import Data.Monoid -------------------------------------------------------------------------------- -- Transforming event values into usable values. --------------------------------------------------------------------------------@@ -88,7 +85,7 @@ -- stream to produce a value. Once both streams have produced a value, combine -- the two using the given combine function and emit an event with the -- value.-latchWith :: Monad m+latchWith :: (Applicative m, Monad m) => (b -> c -> d) -> Var m a (Event b) -> Var m a (Event c) -> Var m a (Event d) latchWith f vb vc = latchWith' (NoEvent, vb) vc@@ -102,7 +99,7 @@ -- | Produces values from the first unless the second produces event -- values and if so, produces the values of those events.-orE :: Monad m => Var m a b -> Var m a (Event b) -> Var m a b+orE :: (Applicative m, Monad m) => Var m a b -> Var m a (Event b) -> Var m a b orE y ye = Var $ \a -> do (b, y') <- runVar y a (e, ye') <- runVar ye a@@ -111,11 +108,9 @@ Event b' -> (b', orE y' ye') -- | Injects the values of the `vb` into the events of `ve`.-tagOn :: Monad m => Var m a b -> Var m a (Event c) -> Var m a (Event b)-tagOn vb ve = proc a -> do- b <- vb -< a- e <- ve -< a- returnA -< b <$ e+tagOn :: (Applicative m, Monad m)+ => Var m a b -> Var m a (Event c) -> Var m a (Event b)+tagOn vb ve = (<$) <$> vb <*> ve -- | Injects a monadic computation into an event stream, using the event -- values of type `b` as a parameter to produce an event stream of type@@ -123,7 +118,7 @@ -- previous event is used in a clean up function. -- -- This is like `tagM` but performs a cleanup function first.---ringM :: Monad m+--ringM :: (Applicative m, Monad m) -- => (c -> m ()) -> (b -> m c) -> Var m a (Event b) -> Var m a (Event c) --ringM cln = (go (const $ return ()) .) . tagM -- where go f ve = Var $ \a -> do (ec, ve') <- runVar ve a@@ -134,7 +129,8 @@ -- | Injects a monadic computation into the events of `vb`, providing a way -- to perform side-effects inside an `Event` inside a `Var`.-tagM :: Monad m => (b -> m c) -> Var m a (Event b) -> Var m a (Event c)+tagM :: (Applicative m, Monad m)+ => (b -> m c) -> Var m a (Event b) -> Var m a (Event c) tagM f vb = Var $ \a -> do (eb, vb') <- runVar vb a case eb of@@ -154,17 +150,17 @@ use a v = (a <$) <$> v -- | Triggers an `Event ()` when the input value is True.-onTrue :: Monad m => Var m Bool (Event ())+onTrue :: (Applicative m, Monad m) => Var m Bool (Event ()) onTrue = var $ \b -> if b then Event () else NoEvent -- | Triggers an `Event a` when the input is `Just a`.-onJust :: Monad m => Var m (Maybe a) (Event a)+onJust :: (Applicative m, Monad m) => Var m (Maybe a) (Event a) onJust = var $ \ma -> case ma of Nothing -> NoEvent Just a -> Event a -- | Triggers an `Event a` when the input is a unique value.-onUnique :: (Monad m, Eq a) => Var m a (Event a)+onUnique :: (Applicative m, Monad m, Eq a) => Var m a (Event a) onUnique = Var $ \a -> return (Event a, trigger a) where trigger a' = Var $ \a'' -> let e = if a' == a'' then NoEvent@@ -176,14 +172,15 @@ onWhen f = var $ \a -> if f a then Event a else NoEvent -- | Wraps all produced values of the given var with events.-toEvent :: Monad m => Var m a b -> Var m a (Event b)+toEvent :: (Applicative m, Monad m) => Var m a b -> Var m a (Event b) toEvent = (~> var Event) -------------------------------------------------------------------------------- -- Using event values -------------------------------------------------------------------------------- -- | Collect all produced values into a monoidal structure using the given -- insert function.-collectWith :: (Monoid b, Monad m) => (a -> b -> b) -> Var m (Event a) b+collectWith :: (Monoid b, Applicative m, Monad m)+ => (a -> b -> b) -> Var m (Event a) b collectWith f = Var $ \a -> collect' mempty a where collect' b e = let b' = case e of NoEvent -> b@@ -192,7 +189,7 @@ -- | Collect all produced values into a list. The latest event value will -- be at the head of the list.-collect :: Monad m => Var m (Event a) [a]+collect :: (Applicative m, Monad m) => Var m (Event a) [a] collect = collectWith (:) -- | Produces the given value until the input events produce a value, then@@ -203,7 +200,7 @@ -- @ -- This is similar to 'hold' except that it takes events from its input value -- instead of another 'Var'.-startingWith, startWith :: Monad m => a -> Var m (Event a) a+startingWith, startWith :: (Applicative m, Monad m) => a -> Var m (Event a) a startingWith = startWith startWith a = Var $ \e -> return $ case e of@@ -211,13 +208,13 @@ Event a' -> (a', startWith a') -- | Flipped version of 'hold'.-holdWith :: Monad m => b -> Var m a (Event b) -> Var m a b+holdWith :: (Applicative m, Monad m) => b -> Var m a (Event b) -> Var m a b holdWith = flip hold -- | Produces the 'initial' value until the given 'Var' produces an event. -- After an event is produced that event's value will be produced until the -- next event produced by the given 'Var'.-hold :: Monad m => Var m a (Event b) -> b -> Var m a b+hold :: (Applicative m, Monad m) => Var m a (Event b) -> b -> Var m a b hold w initial = Var $ \x -> do (mb, w') <- runVar w x return $ case mb of@@ -226,13 +223,15 @@ -- | Produce events after the first until the second. After a successful -- cycle it will start over.-between :: Monad m => Var m a (Event b) -> Var m a (Event c) -> Var m a (Event ())+between :: (Applicative m, Monad m)+ => Var m a (Event b) -> Var m a (Event c) -> Var m a (Event ()) between vb vc = (never `before` vb) `andThenE` (toEvent vu `before` vc) `andThen` between vb vc where vu = pure () -- | Produce events with the initial value only after the input stream has -- produced one event.-after :: Monad m => Var m a b -> Var m a (Event c) -> Var m a (Event b)+after :: (Applicative m, Monad m)+ => Var m a b -> Var m a (Event c) -> Var m a (Event b) after vb ve = Var $ \a -> do (_, vb') <- runVar vb a (e, ve') <- runVar ve a@@ -242,7 +241,7 @@ -- | Like before, but use the value produced by the switching stream to -- create a stream to switch to.-beforeWith :: Monad m+beforeWith :: (Applicative m, Monad m) => Var m a b -> (Var m a (Event b), b -> Var m a (Event b)) -> Var m a (Event b)@@ -255,7 +254,7 @@ -- | Like before, but sample the value of the second stream once before -- inhibiting.-beforeOne :: Monad m => Var m a b -> Var m a (Event b) -> Var m a (Event b)+beforeOne :: (Applicative m, Monad m) => Var m a b -> Var m a (Event b) -> Var m a (Event b) beforeOne vb ve = Var $ \a -> do (b, vb') <- runVar vb a (e, ve') <- runVar ve a@@ -265,12 +264,12 @@ -- | Produce events with the initial varying value only before the second stream -- has produced one event.-before :: Monad m => Var m a b -> Var m a (Event c) -> Var m a (Event b)+before :: (Applicative m, Monad m) => Var m a b -> Var m a (Event c) -> Var m a (Event b) before = until -- | Produce events with the initial varying value until the input event stream -- `ve` produces its first event, then never produce any events.-until :: Monad m => Var m a b -> Var m a (Event c) -> Var m a (Event b)+until :: (Applicative m, Monad m) => Var m a b -> Var m a (Event c) -> Var m a (Event b) until vb ve = Var $ \a -> do (b, vb') <- runVar vb a (e, ve') <- runVar ve a@@ -279,11 +278,11 @@ NoEvent -> return (Event b, vb' `until` ve') -- | Produce the given value once and then inhibit forever.-once :: Monad m => b -> Var m a (Event b)+once :: (Applicative m, Monad m) => b -> Var m a (Event b) once b = Var $ \_ -> return (Event b, never) -- | Stream through some number of successful events and then inhibit forever.-takeE :: Monad m => Int -> Var m a (Event b) -> Var m a (Event b)+takeE :: (Applicative m, Monad m) => Int -> Var m a (Event b) -> Var m a (Event b) takeE n ve = Var $ \a -> do (eb, ve') <- runVar ve a case eb of@@ -291,29 +290,29 @@ Event b -> return (Event b, takeE (n-1) ve') -- | Inhibit all events that don't pass the predicate.-filterE :: Monad m => (b -> Bool) -> Var m a (Event b) -> Var m a (Event b)+filterE :: (Applicative m, Monad m) => (b -> Bool) -> Var m a (Event b) -> Var m a (Event b) filterE p v = v ~> var check where check (Event b) = if p b then Event b else NoEvent check _ = NoEvent -- | Never produces any event values.-never :: Monad m => Var m b (Event c)+never :: (Applicative m, Monad m) => Var m b (Event c) never = pure NoEvent -- | Produces events with the initial value forever.-always :: Monad m => b -> Var m a (Event b)+always :: (Applicative m, Monad m) => b -> Var m a (Event b) always = pure . Event -------------------------------------------------------------------------------- -- Switching on events -------------------------------------------------------------------------------- -- | Produces the first 'Var's Event values until that stops producing, then -- switches to the second 'Var'.-andThen :: Monad m => Var m a (Event b) -> Var m a b -> Var m a b+andThen :: (Applicative m, Monad m) => Var m a (Event b) -> Var m a b -> Var m a b andThen w1 w2 = w1 `andThenWith` const w2 -- | Switches from one event stream to another once the first stops -- producing.-andThenE :: Monad m+andThenE :: (Applicative m, Monad m) => Var m a (Event b) -> Var m a (Event b) -> Var m a (Event b) andThenE y1 y2 = Var $ \a -> do (e, y1') <- runVar y1 a@@ -324,7 +323,7 @@ -- | Switches from one event stream when that stream stops producing. A new -- stream is created using the last produced value (or `Nothing`) and used -- as the second stream.-andThenWith :: Monad m+andThenWith :: (Applicative m, Monad m) => Var m a (Event b) -> (Maybe b -> Var m a b) -> Var m a b andThenWith = go Nothing where go mb w1 f = Var $ \a -> do@@ -335,7 +334,8 @@ -- | Switches using a mode signal. Signals maintain state for the duration -- of the mode.-switchByMode :: (Monad m, Eq b) => Var m a b -> (b -> Var m a c) -> Var m a c+switchByMode :: (Applicative m, Monad m, Eq b)+ => Var m a b -> (b -> Var m a c) -> Var m a c switchByMode switch f = Var $ \a -> do (b, _) <- runVar switch a (_, v) <- runVar (f b) a@@ -351,7 +351,7 @@ -- | Produce events of a varying value 'v' only when its input value passes a -- predicate 'f'. -- 'v' maintains state while cold.-onlyWhen :: Monad m+onlyWhen :: (Applicative m, Monad m) => Var m a b -- ^ 'v' - The varying value -> (a -> Bool) -- ^ 'f' - The predicate to run on 'v''s input values. -> Var m a (Event b)@@ -361,7 +361,7 @@ -- | Produce events of a varying value 'v' only when an event stream 'h' -- produces an event. -- 'v' and 'h' maintain state while cold.-onlyWhenE :: Monad m+onlyWhenE :: (Applicative m, Monad m) => Var m a b -- ^ 'v' - The varying value -> Var m a (Event c) -- ^ 'h' - The event stream -> Var m a (Event b)@@ -376,14 +376,14 @@ -------------------------------------------------------------------------------- -- | Combine two events streams into one event stream. Like `combine` but -- uses a combining function instead of (,).-combineWith :: Monad m+combineWith :: (Applicative m, Monad m) => (b -> c -> d) -> Var m a (Event b) -> Var m a (Event c) -> Var m a (Event d) combineWith f vb vc = (uncurry f <$>) <$> (combine vb vc) -- | Combine two event streams into an event stream of tuples. A tuple is -- only produced when both event streams produce a value.-combine :: Monad m+combine :: (Applicative m, Monad m) => Var m a (Event b) -> Var m a (Event c) -> Var m a (Event (b,c)) combine vb vc = (\eb ec -> (,) <$> eb <*> ec) <$> vb <*> vc --------------------------------------------------------------------------------
src/Control/Varying/Time.hs view
@@ -2,12 +2,12 @@ -- Copyright: (c) 2015 Schell Scivally -- License: MIT -- Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>-{-# LANGUAGE Arrows #-} {-# LANGUAGE TupleSections #-} module Control.Varying.Time where import Control.Varying.Core import Control.Varying.Event hiding (after, before)+import Control.Applicative import Data.Time.Clock -- | Produces "time" deltas using 'getCurrentTime' and 'diffUTCTime'.@@ -16,7 +16,8 @@ -- | Produces "time" deltas using a monadic computation and a difference -- function.-delta :: (Num t, Fractional t, Monad m) => m a -> (a -> a -> t) -> Var m b t+delta :: (Num t, Fractional t, Applicative m, Monad m)+ => m a -> (a -> a -> t) -> Var m b t delta m f = Var $ \_ -> do t <- m return (0, delta' t)@@ -30,7 +31,7 @@ -- | Emits events before accumulating t of input dt. -- Note that as soon as we have accumulated >= t we stop emitting events -- and there is no guarantee that an event will be emitted at time == t.-before :: (Monad m, Num t, Ord t) => t -> Var m t (Event ())+before :: (Applicative m, Monad m, Num t, Ord t) => t -> Var m t (Event ()) before t = Var $ \dt -> do if t - dt >= 0 then return (Event (), before $ t - dt)@@ -39,7 +40,7 @@ -- | Emits events after t input has been accumulated. -- Note that event emission is not guaranteed to begin exactly at t, -- only at some small delta after t.-after :: (Monad m, Num t, Ord t) => t -> Var m t (Event ())+after :: (Applicative m, Monad m, Num t, Ord t) => t -> Var m t (Event ()) after t = Var $ \dt -> do if t - dt <= 0 then return (Event (), pure $ Event ())
src/Control/Varying/Tween.hs view
@@ -15,16 +15,15 @@ -- dreams). ---{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE Arrows #-} {-# LANGUAGE Rank2Types #-} module Control.Varying.Tween ( -- * Creating tweens -- $creation tween,+ constant, -- * Interpolation functions -- $lerping- constant, linear, easeInCirc, easeOutCirc,@@ -55,6 +54,7 @@ import Control.Varying.Event hiding (after, before) import Control.Varying.Time import Control.Arrow+import Control.Applicative -------------------------------------------------------------------------------- -- $lerping@@ -152,11 +152,6 @@ linear :: Num t => Easing t linear c t b = c * t + b --- | Ease none.--- This performs no interpolation over the duration, it just samples at a--- constant value until the duration is up.-constant :: (Monad m, Num t, Ord t) => a -> t -> Var m t (Event a)-constant value duration = use value $ before duration -------------------------------------------------------------------------------- -- $creation --@@ -188,7 +183,7 @@ -- Keep in mind `tween` must be fed time deltas, not absolute time or -- duration. This is mentioned because the author has made that mistake -- more than once ;)-tween :: (Monad m, Fractional t, Ord t)+tween :: (Applicative m, Monad m, Fractional t, Ord t) => Easing t -> t -> t -> t -> Var m t (Event t) tween f start end dur = proc dt -> do -- Current time as percentage / amount of interpolation (0.0 - 1.0)@@ -202,8 +197,14 @@ -- Tag the event with the value. returnA -< x <$ e +-- Creates a tween that performs no interpolation over the duration.+constant :: (Applicative m, Monad m, Num t, Ord t)+ => a -> t -> Var m t (Event a)+constant value duration = use value $ before duration+ -- | Varies 0.0 to 1.0 linearly for duration `t` and 1.0 after `t`.-timeAsPercentageOf :: (Monad m, Ord t, Num t, Fractional t) => t -> Var m t t+timeAsPercentageOf :: (Applicative m, Monad m, Ord t, Num t, Fractional t)+ => t -> Var m t t timeAsPercentageOf t = proc dt -> do t' <- accumulate (+) 0 -< dt returnA -< min 1 (t' / t)
src/Example.hs view
@@ -2,6 +2,7 @@ import Control.Varying import Control.Varying.Time as Time -- time is not auto-exported+import Control.Applicative import Text.Printf -- | A simple 2d point type.@@ -22,7 +23,7 @@ <~ time -- An exponential tween back and forth from 0 to 100 over 2 seconds.-tweenx :: Monad m => Var m Float Float+tweenx :: (Applicative m, Monad m) => Var m Float Float tweenx = -- Tweens only happen for a certain duration and so their sample -- values have the type (Ord t, Fractional t => Event t). After construction@@ -48,7 +49,7 @@ `andThen` tweenx -- A quadratic tween back and forth from 0 to 100 over 2 seconds.-tweeny :: Monad m => Var m Float Float+tweeny :: (Applicative m, Monad m) => Var m Float Float tweeny = tween easeOutQuad 0 100 1 `andThenE` tween easeOutQuad 100 0 1 `andThen` tweeny
varying.cabal view
@@ -10,7 +10,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.1.1.1+version: 0.1.1.2 -- A short (one-line) description of the package. synopsis: Automaton based varying values, event streams and tweening.@@ -74,7 +74,7 @@ -- other-extensions: -- Other library packages from which modules are imported.- build-depends: base >=4.8 && <4.9,+ build-depends: base >=4.7 && <4.9, time >=1.5 && <1.6 -- Directories containing source files.@@ -87,7 +87,7 @@ ghc-options: -Wall -- Other library packages from which modules are imported.- build-depends: base >=4.8 && <4.9,+ build-depends: base >=4.7 && <4.9, time >=1.5 && <1.6