packages feed

varying 0.1.0.2 → 0.1.0.3

raw patch · 6 files changed

+251/−44 lines, 6 files

Files

README.md view
@@ -5,7 +5,7 @@ [auto](http://hackage.haskell.org/package/auto) packages. Unlike netwire the  concepts of inhibition and time are explicit (through `Control.Varying.Event`  and `Control.Varying.Time`) and the library aims at being minimal and well -documented with a small API surface area.+documented with a small API.  Depending on your types and values varying can provide discrete or continuous time semantics.
src/Control/Varying.hs view
@@ -1,7 +1,34 @@--- | Module:     Control.Varying---   Copyright:  (c) 2015 Schell Scivally---   License:    MIT---   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>+-- |+--  Module:     Control.Varying+--  Copyright:  (c) 2015 Schell Scivally+--  License:    MIT+--  Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>+--+--  The simplest, squishiest FRP library around.+--+--  [@Core@]+--  Get started writing varying values (also called streams) using the pure+--  constructor 'var', the monadic constructor 'varM' or the raw constructor+--  'Var'+--+--  [@Event@]+--  Write event streams using the many event emitters and combinators.+--+--  [@Tween@]+--  Tween numerical values over time using interpolation functions and the+--  "quick 'n dirty" time generators in 'Control.Varying.Time'.+--+--  [@Time@]+--  The 'Control.Varying.Time' module is not reexported because some of the+--  functions collide with those in 'Event' - namely 'before' and 'after'.+--  I think this is okay because in my experience most modules will either+--  deal with events based on user input or events based on time, an in+--  rare cases both - but in that case the majority of streams will be of one+--  type making the choice of which module to import qualified an easy one.+--  The time generator 'Control.Varying.Time.deltaUTC' in 'Control.Varying.Time'+--  is practical and based on 'Data.Time.Clock.getCurrentTime'. It's meant+--  to be simple, not optimal.+-- module Control.Varying (     -- * Reexports     module Control.Varying.Core,
src/Control/Varying/Core.hs view
@@ -1,8 +1,44 @@--- | Module:     Control.Varying.Core+-- |+--   Module:     Control.Varying.Core --   Copyright:  (c) 2015 Schell Scivally --   License:    MIT --   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>-module Control.Varying.Core where+--+--   Values that change over a given domain.+--+--   Varying values take some input (the domain ~ time, place, etc) and produce+--   a sample and a new varying value. This pattern is known as an automaton.+--   `varying` uses this pattern as its base type with the additon of a monadic+--   computation to create locally stateful signals that change over some+--   domain.+module Control.Varying.Core (+    Var(..),+    -- * Creating varying values+    -- $creation+    var,+    varM,+    -- * Composing varying values+    -- $composition+    (<~),+    (~>),+    -- * Adjusting and accumulating+    delay,+    accumulate,+    -- * Sampling varying values (running, entry points)+    -- $running+    evalVar,+    execVar,+    loopVar,+    loopVar_,+    whileVar,+    whileVar_,+    -- * Testing varying values+    testVar,+    testVar_,+    testWhile_,+    vtrace,+    vstrace+) where  import Prelude hiding (id, (.)) import Control.Arrow@@ -10,7 +46,36 @@ import Control.Applicative import Debug.Trace ----------------------------------------------------------------------------------- Constructing+-- $creation+-- You can create a pure varying value by lifting a function @(a -> b)@+-- with 'var':+--+-- @+-- addsOne :: Monad m => Var m Int Int+-- addsOne = var (+1)+-- @+--+-- 'var' is also equivalent to 'arr'.+--+-- You can create a monadic varying value by lifting a monadic computation+-- @(a -> m b)@ using 'varM':+--+-- @+-- getsFile :: Var IO FilePath String+-- getsFile = varM readFile+-- @+--+-- You can create either with the raw constructor. You can also create your+-- own combinators using the raw constructor, as it allows you full control+-- over how varying values are stepped and sampled:+--+-- @+-- delay :: Monad m => b -> Var m a b -> Var m a b+-- delay b v = Var $ \a -> return (b, go a v)+--     where go a v' = Var $ \a' -> do (b', v'') <- runVar v' a+--                                     return (b', go a' v'')+-- @+-- -------------------------------------------------------------------------------- -- | Lift a pure computation into a 'Var'. var :: Applicative a => (b -> c) -> Var a b c@@ -22,8 +87,18 @@     b <- f a     return (b, varM f) ----------------------------------------------------------------------------------- Running+-- $running+-- The easiest way to sample a 'Var' is to run it in the desired monad with+-- 'runVar'. This will give you a sample value and a new 'Var' bundled up in a+-- tuple:+--+-- > do (sample, v') <- runVar v inputValue+--+-- Much like Control.Monad.State there are other entry points for running+-- varying values like 'evalVar', 'execVar'. There are also extra control+-- structures like 'loopVar' and 'whileVar' and more. --------------------------------------------------------------------------------+ -- | Iterate a 'Var' once and return the sample value. evalVar :: Functor m => Var m a b -> a -> m b evalVar v a = fst <$> (runVar v a)@@ -91,7 +166,7 @@ testVar_ :: Show b => Var IO () b -> IO () testVar_ v = loopVar_ $ pure () ~> v ~> varM print ~> varM (const $ getLine) ----------------------------------------------------------------------------------- Composition and accumulation+-- Adjusting and accumulating -------------------------------------------------------------------------------- -- | Accumulates input values using a folding function and yields -- that accumulated value each sample.@@ -103,12 +178,20 @@ -- | Delays the given 'Var' by one sample using a parameter as the first -- sample. This enables the programmer to create 'Var's that depend on -- themselves for values. For example:--- >  let v = 1 + delay 0 v in testVar_ v+--+-- > let v = 1 + delay 0 v in testVar_ v delay :: Monad m => b -> Var m a b -> Var m a b delay b v = Var $ \a -> return (b, go a v)     where go a v' = Var $ \a' -> do (b', v'') <- runVar v' a                                     return (b', go a' v'')-+--------------------------------------------------------------------------------+-- $composition+-- You can compose varying values together using '~>' and '<~'. The "right plug"+-- ('~>') takes the output from a varying value on the left and "plugs" it+-- into the input of the varying value on the right. The "left plug" does+-- the same thing only in the opposite direction. This allows you to write+-- varying values that read naturally.+-------------------------------------------------------------------------------- -- | Same as '~>' with flipped parameters. (<~) :: Monad m => Var m b c -> Var m a b -> Var m a c (<~) = flip (~>)@@ -210,9 +293,8 @@ -------------------------------------------------------------------------------- -- | The vessel of a varying value. A 'Var' is a structure that contains a value -- that changes over some input. That input could be time (Float, Double, etc)--- or events or a stream of 'Char' - whatever. Similar to the--- 'Control.Monad.State' monad.--- A kind of Mealy machine (an automaton) with effects.+-- or 'Control.Varying.Event.Event's or 'Char' - whatever.+-- It's a kind of Mealy machine (an automaton) with effects. data Var m b c =      Var { runVar :: b -> m (c, Var m b c)                   -- ^ Given an input value, return a computation that
src/Control/Varying/Event.hs view
@@ -1,7 +1,16 @@--- | Module:     Control.Varying.Event+-- |+--   Module:     Control.Varying.Event --   Copyright:  (c) 2015 Schell Scivally --   License:    MIT --   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>+--+--  'Event' streams describe things that happen at a specific time or place+--  or value in general. For example, you can think of the event stream+--  @Var IO Double (Event ())@ as an occurrence of `()` at a specific time+--  (`Double`).+--+--  You can use 'Event' just like you would 'Maybe'.+-- {-# LANGUAGE Arrows #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE PartialTypeSignatures #-}@@ -10,12 +19,12 @@     -- * Transforming event values.     toMaybe,     isEvent,-    -- * Combining events and values+    -- * Combining event streams and value streams     latchWith,     orE,     tagOn,     tagM,-    ringM,+    --ringM,     -- * Generating events from values     use,     onTrue,@@ -23,13 +32,13 @@     onUnique,     onWhen,     toEvent,-    -- * Using events+    -- * Using event streams     collect,     hold,     holdWith,     startingWith,     startWith,-    -- * Temporal operations+    -- * Temporal operations (time - related)     between,     until,     after,@@ -73,8 +82,9 @@ -- Combining varying values and events -------------------------------------------------------------------------------- -- | Holds the last value of one event stream while waiting for another event--- stream to produce a value. Once both streams have produced a value combine--- the two using the given combine function.+-- 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           => (b -> c -> d) -> Var m a (Event b) -> Var m a (Event c)           -> Var m a (Event d)@@ -87,7 +97,6 @@                                       , latchWith' (eb'', vb'') vc''                                       ) - -- | 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@@ -111,14 +120,14 @@ -- previous event is used in a clean up function. -- -- This is like `tagM` but performs a cleanup function first.-ringM :: 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-                                   case ec of-                                       NoEvent -> return (ec, go f ve')-                                       Event c -> do f c-                                                     return (ec, go cln ve')+--ringM :: 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+--                                   case ec of+--                                       NoEvent -> return (ec, go f ve')+--                                       Event c -> do f c+--                                                     return (ec, go cln ve')  -- | Injects a monadic computation into the events of `vb`, providing a way -- to perform side-effects inside an `Event` inside a `Var`.@@ -401,5 +410,12 @@     fmap f (Event a) = Event $ f a     fmap _ NoEvent = NoEvent --- | An Event is just like a Maybe.+-- | For all intents and purposes you can think of an Event as a Maybe.+-- A value of @Event ()@ means that an event has occurred and that the+-- result is a @()@. A value of @NoEvent@ means that an event did not+-- occur.+--+-- Event streams (like @Var m a (Event b)@) describe events that may occur over+-- varying @a@ (also known as the series of @a@). Usually @a@ would be some+-- form of time or some user input type. data Event a = Event a | NoEvent deriving (Eq)
src/Control/Varying/Tween.hs view
@@ -1,17 +1,69 @@--- | Module:     Control.Varying.Tween+-- |+--   Module:     Control.Varying.Tween --   Copyright:  (c) 2015 Schell Scivally --   License:    MIT --   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>+--+--   Tweening is a technique of generating intermediate samples of a type+--   __between__ a start and end value. By sampling a running tween+--   each frame we get a smooth animation of a value over time.+--+--   At first release `varying` is only capable of tweening numerical+--   values of type @(Fractional t, Ord t) => t@ that match the type of+--   time you use. At some point it would be great to be able to tween+--   arbitrary types, and possibly tween one type into another (pipe+--   dreams).++-- {-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE Arrows #-} {-# LANGUAGE Rank2Types #-}-module Control.Varying.Tween where+module Control.Varying.Tween (+    -- * Creating tweens+    -- $creation+    tween,+    -- * Interpolation functions+    -- $lerping+    constant,+    linear,+    easeInCirc,+    easeOutCirc,+    easeInOutCirc,+    easeInExpo,+    easeOutExpo,+    easeInOutExpo,+    easeInSine,+    easeOutSine,+    easeInOutSine,+    easeInPow,+    easeOutPow,+    easeInOutPow,+    easeInCubic,+    easeOutCubic,+    easeInOutCubic,+    easeInQuad,+    easeOutQuad,+    easeInOutQuad,+    -- * Interpolation helpers+    easeInOut,+    -- * Writing your own tweens+    Tween,+    Easing+) where  import Control.Varying.Core import Control.Varying.Event hiding (after, before) import Control.Varying.Time import Control.Arrow +--------------------------------------------------------------------------------+-- $lerping+-- These pure functions take a `c` (total change in value, ie end - start),+-- `t` (percent of duration completion) and `b` (start value) and result in+-- and interpolation of a value. To see what these look like please check+-- out http://www.gizma.com/easing/.+--------------------------------------------------------------------------------+ -- | Ease in quadratic. easeInQuad :: Num t => Easing t easeInQuad c t b =  c * t*t + b@@ -36,6 +88,10 @@ easeInOutCubic :: (Ord t, Fractional t) => Easing t easeInOutCubic = easeInOut easeInCubic easeOutCubic +-- | Ease in and out by some power.+easeInOutPow :: (Fractional t, Ord t) => Int -> Easing t+easeInOutPow p = easeInOut (easeInPow p) (easeOutPow p)+ -- | Ease in by some power. easeInPow :: Num t => Int -> Easing t easeInPow power c t b =  c * (t^power) + b@@ -101,16 +157,27 @@ -- 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---- | An easing function.-type Easing t = t -> t -> t -> t---- | A linear interpolation between two values over some duration.-type Tween m t = t -> t -> t -> Var m t (Event t)+--------------------------------------------------------------------------------+-- $creation+--+-- The standard way to start tweening values is to use 'tween' along with+-- an interpolation function such as 'easeInOutExpo'. For example,+-- @tween easeInOutExpo 0 100 10@, this will create an event stream that+-- produces @Event t@s where `t` is tweened from 0 to 100 over 10 seconds.+-- Once the 10 seconds are up, the stream will inhibit (produce `NoEvent`)+-- forever. To create a stream of `t` that is tweened from 0 to 100 and+-- then stays at 100 forever after requires you to use a combinator from the+-- 'Event' module, like so:+--+-- >tween easeInOutExpo 0 100 10 `andThen` 100+--+-- The 'andThen' combinator "disolves" our 'Event's by switching to+-- another stream once the first inhibits.+-------------------------------------------------------------------------------- --- | Produces an event sample interpolated between a start and end value--- using an easing equation ('Easing') over a duration. The resulting 'Var' will--- take a time delta as input. For example:+-- | Creates an event stream that produces an event value interpolated between+-- a start and end value using an easing equation ('Easing') over a duration.+-- The resulting 'Var' will take a time delta as input. For example: -- -- @ -- testWhile_ isEvent v@@ -140,3 +207,18 @@ timeAsPercentageOf t = proc dt -> do     t' <- accumulate (+) 0 -< dt     returnA -< min 1 (t' / t)++-- | An easing function. The parameters or often named `c`, `t` and `b`,+-- where `c` is the total change in value over the complete duration+-- (endValue - startValue), `t` is the current percentage of the duration+-- that has elapsed and `b` is the start value.+--+-- To make things simple only numerical values can be tweened and the type+-- of time deltas much match the tween's value type. This may change in the+-- future :)+type Easing t = t -> t -> t -> t++-- | A linear interpolation between two values over some duration.+-- A `Tween` takes three values - a start value, an end value and+-- a duration.+type Tween m t = t -> t -> t -> Var m t (Event t)
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.0.2+version:             0.1.0.3  -- A short (one-line) description of the package. synopsis:            Automaton based varying values, event streams and tweening.