diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,84 +2,76 @@
 [![Hackage](https://img.shields.io/hackage/v/varying.svg)](http://hackage.haskell.org/package/varying)
 [![Build Status](https://travis-ci.org/schell/varying.svg)](https://travis-ci.org/schell/varying)
 
-This library provides automaton based varying values useful for both functional
+This library provides automaton based value streams 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 
 [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 
+and `Control.Varying.Time`). The library aims at being minimal and well 
 documented with a small API.
 
-Depending on your types and values varying can provide discrete or continuous
-time semantics.
-
 ## Getting started
 
 ```haskell
 module Main where
 
 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.
-data Point = Point { x :: Float
-                   , y :: Float
+data Point = Point { px :: Float
+                   , py :: Float
                    } deriving (Show, Eq)
 
--- | Our Point value that varies over time continuously in x and y.
-backAndForth :: Var IO a Point
-backAndForth =
-    -- Here we use Applicative to construct a varying Point that takes time
-    -- as an input.
-    (Point <$> tweenx <*> tweeny)
-        -- Here we feed the varying Point a time signal using the 'plug left'
-        -- function. We could similarly use the 'plug right' (~>) function
-        -- and put the time signal before the Point. This is needed because the
-        -- tweens take time as an input.
-        <~ time
-
--- An exponential tween back and forth from 0 to 100 over 2 seconds.
-tweenx :: 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
-    -- a tween's full type will be
-    -- (Ord t, Fractional t, Monad m) => Var m t (Event t).
-     tween easeOutExpo 0 100 1
-         -- We can chain another tween back to the starting position using
-         -- `andThenE`, which will sample the first tween until it ends and then
-         -- switch to sampling the next tween.
-         `andThenE`
-             -- Tween back to the starting position.
-             tween easeOutExpo 100 0 1
-                 -- At this point our resulting sample values will still have the
-                 -- type (Event Float). The tween as a whole will be an event
-                 -- stream. The tween also only runs back and forth once. We'd
-                 -- like the tween to loop forever so that our point cycles back
-                 -- and forth between 0 and 100 indefinitely.
-                 -- We can accomplish this with recursion and the `andThen`
-                 -- combinator, which samples an event stream until it
-                 -- inhibits and then switches to a normal value stream (a
-                 -- varying value). Put succinctly, it disolves our events into
-                 -- values.
-                 `andThen` tweenx
+-- An exponential tween back and forth from 0 to 100 over 2 seconds that
+-- loops forever. This spline takes float values of delta time as input,
+-- outputs the current x value at every step and would result in () if it
+-- terminated.
+tweenx :: (Applicative m, Monad m) => Spline Float Float m ()
+tweenx = do
+    -- Tween from 0 to 100 over 1 second
+    x <- tween easeOutExpo 0 100 1
+    -- Chain another tween back to the starting position
+    _ <- tween easeOutExpo x 0 1
+    -- Loop forever
+    tweenx
 
--- A quadratic tween back and forth from 0 to 100 over 2 seconds.
-tweeny :: Monad m => Var m Float Float
-tweeny =
-    tween easeOutQuad 0 100 1 `andThenE` tween easeOutQuad 100 0 1 `andThen` tweeny
+-- A quadratic tween back and forth from 0 to 100 over 2 seconds that never
+-- ends.
+tweeny :: (Applicative m, Monad m) => Spline Float Float m ()
+tweeny = do
+    y <- tween easeOutQuad 0 100 1
+    _ <- tween easeOutQuad y 0 1
+    tweeny
 
--- Our time signal.
+-- Our time signal that provides delta time samples.
 time :: Var IO a Float
 time = deltaUTC
 
+-- | Our Point value that varies over time continuously in x and y.
+backAndForth :: Var IO a Point
+backAndForth =
+    -- Turn our splines back into continuous value streams. We must provide
+    -- a starting value since splines are not guaranteed to be defined at
+    -- their edges.
+    let x = execSpline 0 tweenx
+        y = execSpline 0 tweeny
+    in
+    -- Construct a varying Point that takes time as an input.
+    (Point <$> x <*> y)
+        -- Stream in a time signal using the 'plug left' combinator.
+        -- We could similarly use the 'plug right' (~>) function
+        -- and put the time signal before the construction above. This is needed
+        -- because the tween streams take time as an input.
+        <~ time
+
 main :: IO ()
 main = do
-    putStrLn "Varying Values"
+    putStrLn "Varying Example"
     loop backAndForth
         where loop :: Var IO () Point -> IO ()
               loop v = do (point, vNext) <- runVar v ()
-                          printf "\nPoint %03.1f %03.1f" (x point) (y point)
+                          printf "\nPoint %03.1f %03.1f" (px point) (py point)
                           loop vNext
 ```
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -2,3 +2,4 @@
 ==========
 
 0.1.5.0 - added Control.Varying.Spline
+0.2.0.0 - reordered spline type variables for MonadTrans
diff --git a/src/Control/Varying.hs b/src/Control/Varying.hs
--- a/src/Control/Varying.hs
+++ b/src/Control/Varying.hs
@@ -4,38 +4,34 @@
 --  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'
+--  Get started writing value 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.
 --
+--  [@Spline@]
+--  Use do-notation to sequence event streams to form complex behavior.
+--
 --  [@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.
+--  Create time streams and temporal event streams.
 --
 module Control.Varying (
     -- * Reexports
     module Control.Varying.Core,
     module Control.Varying.Event,
-    module Control.Varying.Tween
+    module Control.Varying.Spline,
+    module Control.Varying.Time,
+    module Control.Varying.Tween,
 ) where
 
 import Control.Varying.Core
 import Control.Varying.Event
 import Control.Varying.Tween
+import Control.Varying.Time
+import Control.Varying.Spline
diff --git a/src/Control/Varying/Core.hs b/src/Control/Varying/Core.hs
--- a/src/Control/Varying/Core.hs
+++ b/src/Control/Varying/Core.hs
@@ -4,28 +4,28 @@
 --   License:    MIT
 --   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>
 --
---   Values that change over a given domain.
+--   Value streams represent 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.
+--   A stream takes some input (the domain e.g. time, place, etc) and when
+--   sampled using 'runVar' - produces a value and a new value stream. 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
+    -- * Creating value streams
     -- $creation
     var,
     varM,
     mkState,
-    -- * Composing varying values
+    -- * Composing value streams
     -- $composition
     (<~),
     (~>),
     -- * Adjusting and accumulating
     delay,
     accumulate,
-    -- * Sampling varying values (running, entry points)
+    -- * Sampling value streams (running and other entry points)
     -- $running
     evalVar,
     execVar,
@@ -33,7 +33,7 @@
     loopVar_,
     whileVar,
     whileVar_,
-    -- * Testing varying values
+    -- * Testing value streams
     testVar,
     testVar_,
     testWhile_,
@@ -51,7 +51,7 @@
 import Debug.Trace
 --------------------------------------------------------------------------------
 -- $creation
--- You can create a pure varying value by lifting a function @(a -> b)@
+-- You can create a pure value stream by lifting a function @(a -> b)@
 -- with 'var':
 --
 -- @
@@ -59,9 +59,9 @@
 -- addsOne = var (+1)
 -- @
 --
--- 'var' is also equivalent to 'arr'.
+-- 'var' is equivalent to 'arr'.
 --
--- You can create a monadic varying value by lifting a monadic computation
+-- You can create a monadic value stream by lifting a monadic computation
 -- @(a -> m b)@ using 'varM':
 --
 -- @
@@ -71,7 +71,7 @@
 --
 -- 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:
+-- over how value streams are stepped and sampled:
 --
 -- @
 -- delay :: Monad m => b -> Var m a b -> Var m a b
@@ -101,17 +101,15 @@
   return (b', mkState f s')
 --------------------------------------------------------------------------------
 -- $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:
+-- The easiest way to sample a stream is to run it in the desired monad with
+-- 'runVar'. This will produce a sample value and a new stream.
 --
 -- > 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.
+-- value streams like 'evalVar', 'execVar'. There are also extra control
+-- structures such as 'loopVar' and 'whileVar'.
 --------------------------------------------------------------------------------
-
 -- | 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
@@ -193,8 +191,8 @@
     let b' = f b a
     return (b', accumulate f b')
 
--- | 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
+-- | Delays the given stream by one sample using the argument as the first
+-- sample. This enables the programmer to create streams that depend on
 -- themselves for values. For example:
 --
 -- > let v = 1 + delay 0 v in testVar_ v
@@ -204,11 +202,11 @@
                                     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.
+-- You can compose value streams together using '~>' and '<~'. The "right plug"
+-- ('~>') takes the output from a value stream on the left and "plugs" it
+-- into the input of the value stream on the right. The "left plug" does
+-- the same thing in the opposite direction. This allows you to write value
+-- streams that read naturally.
 --------------------------------------------------------------------------------
 -- | Same as '~>' with flipped parameters.
 (<~) :: Monad m => Var m b c -> Var m a b -> Var m a c
@@ -316,7 +314,7 @@
 --------------------------------------------------------------------------------
 -- Core datatypes
 --------------------------------------------------------------------------------
--- | The vessel of a varying value. A 'Var' is a structure that contains a value
+-- | The vessel of a value stream. A 'Var' is a structure that contains a value
 -- that changes over some input. That input could be time (Float, Double, etc)
 -- or 'Control.Varying.Event.Event's or 'Char' - whatever.
 -- It's a kind of Mealy machine (an automaton) with effects.
diff --git a/src/Control/Varying/Event.hs b/src/Control/Varying/Event.hs
--- a/src/Control/Varying/Event.hs
+++ b/src/Control/Varying/Event.hs
@@ -4,61 +4,42 @@
 --   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'.
+--  'Event' streams describe things that happen at a specific domain.
+--  For example, you can think of the event stream
+--  @Var IO Double (Event ())@ as an occurrence of () at a specific input
+--  of type 'Double'.
 --
+--  For sequencing streams please check out 'Control.Varying.Spline' which
+--  lets you chain together sequences of event streams using do-notation.
 module Control.Varying.Event (
     Event(..),
     -- * Transforming event values.
     toMaybe,
     isEvent,
-    -- * Combining event streams and value streams
-    latchWith,
+    -- * Combining event and value streams
     orE,
-    tagOn,
-    tagM,
-    --ringM,
-    -- * Generating events from values
+    -- * Generating events from value streams
     use,
     onTrue,
     onJust,
     onUnique,
     onWhen,
-    toEvent,
-    -- * Using event streams
+    -- * Folding and gathering event streams
     foldStream,
-    collect,
-    collectWith,
-    hold,
-    holdWith,
-    startingWith,
-    startWith,
-    -- * Temporal operations (time - related)
-    between,
-    after,
-    beforeWith,
-    beforeOne,
-    before,
+    startingWith, startWith,
+    -- * List-like operations on event streams
     filterE,
     takeE,
     dropE,
+    -- * Primitive event streams
     once,
     always,
     never,
-    -- * Switching and chaining events
-    andThen,
-    andThenWith,
-    andThenE,
+    -- * Switching
     switchByMode,
+    -- * Bubbling
     onlyWhen,
     onlyWhenE,
-    -- * Combining event streams
-    combineWith,
-    combine
 ) where
 
 import Prelude hiding (until)
@@ -67,7 +48,7 @@
 import Control.Monad
 import Data.Monoid
 --------------------------------------------------------------------------------
--- Transforming event values into usable values.
+-- Transforming event values into usable values
 --------------------------------------------------------------------------------
 -- | Turns an 'Event' into a 'Maybe'.
 toMaybe :: Event a -> Maybe a
@@ -80,24 +61,8 @@
 isEvent (Event _) = True
 isEvent _ = False
 --------------------------------------------------------------------------------
--- Combining varying values and events
+-- Combining value streams 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 and emit an event with the
--- value.
-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 = latchWith' (NoEvent, vb)
-    where latchWith' (eb, vb') vc =
-              Var $ \a -> do (eb', vb'') <- runVar vb' a
-                             (ec', vc') <- runVar vc a
-                             let eb'' = eb' <|> eb
-                             return ( f <$> eb'' <*> ec'
-                                    , 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 :: (Applicative m, Monad m) => Var m a b -> Var m a (Event b) -> Var m a b
@@ -107,37 +72,6 @@
     return $ case e of
         NoEvent  -> (b, orE y' ye')
         Event b' -> (b', orE y' ye')
-
--- | Injects the values of the `vb` into the events of `ve`.
-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
--- `c`. After the first time an event is generated the result of the
--- previous event is used in a clean up function.
---
--- This is like `tagM` but performs a cleanup function first.
---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
---                                   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`.
-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
-        Event b -> do c <- f b
-                      return (Event c, tagM f vb')
-        NoEvent -> return (NoEvent, tagM f vb')
 --------------------------------------------------------------------------------
 -- Generating events from values
 --------------------------------------------------------------------------------
@@ -171,23 +105,9 @@
 -- | Triggers an `Event a` when the condition is met.
 onWhen :: Applicative m => (a -> Bool) -> Var m a (Event a)
 onWhen f = var $ \a -> if f a then Event a else NoEvent
-
--- | Wraps all produced values of the given var with events.
-toEvent :: (Applicative m, Monad m) => Var m a b -> Var m a (Event b)
-toEvent = (~> var Event)
 --------------------------------------------------------------------------------
--- Using event values
+-- Collecting
 --------------------------------------------------------------------------------
--- | Collect all produced values into a monoidal structure using the given
--- insert function.
-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
-                                        Event a' -> f a' b
-                          in return (b', Var $ \a' -> collect' b' a')
-
 -- | Like a left fold over all the stream's produced values.
 foldStream :: Monad m => (a -> t -> a) -> a -> Var m (Event t) a
 foldStream f acc = Var $ \e ->
@@ -196,95 +116,15 @@
                    in return (acc', foldStream f acc')
         NoEvent -> return (acc, foldStream f acc)
 
--- | Collect all produced values into a list. The latest event value will
--- be at the head of the list.
-collect :: (Applicative m, Monad m) => Var m (Event a) [a]
-collect = collectWith (:)
-
 -- | Produces the given value until the input events produce a value, then
 -- produce that value until a new input event produces. This always holds
 -- the last produced value, starting with the given value.
 -- @
 -- time ~> after 3 ~> startingWith 0
 -- @
--- This is similar to 'hold' except that it takes events from its input value
--- instead of another 'Var'.
 startingWith, startWith :: (Applicative m, Monad m) => a -> Var m (Event a) a
 startingWith = startWith
-startWith a = Var $ \e ->
-    return $ case e of
-                 NoEvent  -> (a, startWith a)
-                 Event a' -> (a', startWith a')
-
--- | Flipped version of 'hold'.
-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 :: (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
-        NoEvent -> (initial, hold w' initial)
-        Event e -> (e, hold w' e)
-
--- | Produce events after the first until the second. After a successful
--- cycle it will start over.
-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 :: (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
-    case e of
-        Event _ -> return (NoEvent, toEvent vb')
-        NoEvent -> return (NoEvent, vb' `after` ve')
-
--- | Like before, but use the value produced by the switching stream to
--- create a stream to switch to.
-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)
-beforeWith vb (ve, f) = Var $ \a -> do
-    (b, vb') <- runVar vb a
-    (e, ve') <- runVar ve a
-    case e of
-        Event b' -> runVar (f b') a
-        NoEvent  -> return (Event b, beforeWith vb' (ve', f))
-
--- | Like before, but sample the value of the second stream once before
--- inhibiting.
-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
-    case e of
-        Event b' -> return (Event b', never)
-        NoEvent  -> return (Event b, vb' `beforeOne` ve')
-
--- | Produce events of the initial varying value until the given event stream
--- produces its first event, then inhibit forever.
-before :: (Applicative m, Monad m)
-       => Var m a b -> Var m a (Event c) -> Var m a (Event b)
-before vb ve = Var $ \a -> do
-    (b, vb') <- runVar vb a
-    (e, ve') <- runVar ve a
-    case e of
-        Event _ -> return (NoEvent, never)
-        NoEvent -> return (Event b, vb' `before` ve')
-
--- | Produce the given value once and then inhibit forever.
-once :: (Applicative m, Monad m) => b -> Var m a (Event b)
-once b = Var $ \_ -> return (Event b, never)
+startWith = foldStream (\_ a -> a)
 
 -- | Stream through some number of successful events and then inhibit forever.
 takeE :: (Applicative m, Monad m)
@@ -312,6 +152,12 @@
 filterE p v = v ~> var check
     where check (Event b) = if p b then Event b else NoEvent
           check _ = NoEvent
+--------------------------------------------------------------------------------
+-- Primitive event streams
+--------------------------------------------------------------------------------
+-- | Produce the given value once and then inhibit forever.
+once :: (Applicative m, Monad m) => b -> Var m a (Event b)
+once b = Var $ \_ -> return (Event b, never)
 
 -- | Never produces any event values.
 never :: (Applicative m, Monad m) => Var m b (Event c)
@@ -321,36 +167,9 @@
 always :: (Applicative m, Monad m) => b -> Var m a (Event b)
 always = pure . Event
 --------------------------------------------------------------------------------
--- Switching on events
+-- Switching
 --------------------------------------------------------------------------------
--- | Produces the first 'Var's Event values until that stops producing, then
--- switches to the second 'Var'.
-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 :: (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
-    case e of
-        NoEvent -> runVar y2 a
-        Event b -> return (Event b, y1' `andThenE` y2)
-
--- | 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 :: (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
-              (e, w1') <- runVar w1 a
-              case e of
-                  NoEvent -> runVar (f mb) a
-                  Event b -> return (b, go (Just b) w1' f)
-
--- | Switches using a mode signal. Signals maintain state for the duration
+-- | Switches using a mode signal. Streams maintain state only for the duration
 -- of the mode.
 switchByMode :: (Applicative m, Monad m, Eq b)
              => Var m a b -> (b -> Var m a c) -> Var m a c
@@ -365,22 +184,24 @@
                       where vOf eb = case eb of
                                          NoEvent -> v
                                          Event b -> f b
-
--- | Produce events of a varying value 'v' only when its input value passes a
+--------------------------------------------------------------------------------
+-- Bubbling
+--------------------------------------------------------------------------------
+-- | Produce events of a value stream 'v' only when its input value passes a
 -- predicate 'f'.
 -- 'v' maintains state while cold.
 onlyWhen :: (Applicative m, Monad m)
-         => Var m a b -- ^ 'v' - The varying value
+         => Var m a b -- ^ 'v' - The value stream
          -> (a -> Bool) -- ^ 'f' - The predicate to run on 'v''s input values.
          -> Var m a (Event b)
 onlyWhen v f = v `onlyWhenE` hot
     where hot = var id ~> onWhen f
 
--- | Produce events of a varying value 'v' only when an event stream 'h'
+-- | Produce events of a value stream 'v' only when an event stream 'h'
 -- produces an event.
 -- 'v' and 'h' maintain state while cold.
 onlyWhenE :: (Applicative m, Monad m)
-          => Var m a b -- ^ 'v' - The varying value
+          => Var m a b -- ^ 'v' - The value stream
           -> Var m a (Event c) -- ^ 'h' - The event stream
           -> Var m a (Event b)
 onlyWhenE v hot = Var $ \a -> do
@@ -390,22 +211,7 @@
             return (Event b, onlyWhenE v' hot')
     else return (NoEvent, onlyWhenE v hot')
 --------------------------------------------------------------------------------
--- Combining event streams
---------------------------------------------------------------------------------
--- | Combine two events streams into one event stream. Like `combine` but
--- uses a combining function instead of (,).
-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 :: (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
---------------------------------------------------------------------------------
--- Operations on Events
+-- Event typeclass instances
 --------------------------------------------------------------------------------
 instance Show a => Show (Event a) where
     show (Event a) = "Event " ++ show a
@@ -431,7 +237,9 @@
     signum = fmap signum
     fromInteger = pure . fromInteger
 
-instance MonadPlus Event
+instance MonadPlus Event where
+    mzero = mempty
+    mplus = (<|>)
 
 instance Monad Event where
    return = Event
@@ -460,8 +268,7 @@
     fmap f (Event a) = Event $ f a
     fmap _ NoEvent = NoEvent
 
--- | 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
+-- | 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.
 --
diff --git a/src/Control/Varying/Spline.hs b/src/Control/Varying/Spline.hs
--- a/src/Control/Varying/Spline.hs
+++ b/src/Control/Varying/Spline.hs
@@ -4,23 +4,24 @@
 --   License:    MIT
 --   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>
 --
---  Using splines we can easily create continuously varying values from
+--  Using splines we can easily create continuous value streams from
 --  multiple piecewise event streams. A spline is a monadic layer on top of
 --  event streams which are only continuous over a certain domain. The idea
 --  is that we use do notation to "run an event stream" from which we will
---  consume produced values. Once the event stream inhibits the do-notation
---  computation completes and returns a result value. That result value is then
---  used to determine the next spline in the sequence. This allows us to build
---  up long, complex behaviors sequentially using a very familiar notation
---  that can be easily turned into a continuously varying value.
-
+--  consume produced values. Once the event stream inhibits the computation
+--  completes and returns a result value. That result value is then
+--  used to determine the next spline in the sequence.
+--
+--  A spline can be converted back into a value stream using 'execSpline' or
+--  'execSplineT'. This allows us to build long, complex, sequential behaviors
+--  using familiar notation.
+--
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE TupleSections #-}
 module Control.Varying.Spline (
     -- * Spline
     Spline,
-    runSpline,
     execSpline,
     spline,
     -- * Spline Transformer
@@ -28,8 +29,12 @@
     runSplineT,
     evalSplineT,
     execSplineT,
-    varyUntilEvent,
+    -- * Special operations.
+    untilEvent,
+    race,
+    mix,
     capture,
+    mapOutput,
     -- * Step
     Step(..),
 ) where
@@ -37,6 +42,8 @@
 import Control.Varying.Core
 import Control.Varying.Event
 import Control.Monad.IO.Class
+import Control.Monad.Trans.Class
+import Control.Monad
 import Control.Applicative
 import Data.Monoid
 
@@ -54,6 +61,10 @@
 stepResult :: Step f b -> Event b
 stepResult (Step _ b) = b
 
+toIter :: (Functor f, Monoid (f b))
+         => (f a -> f b) -> Step (f a) c -> Step (f b) c
+toIter f (Step a b) = Step (f a) b
+
 -- | A discrete step is a functor by applying a function to the contained
 -- event's value.
 instance Functor (Step f) where
@@ -80,24 +91,24 @@
 -- Much like the State monad it has an "internal state" and an eventual
 -- return value, where the internal state is the output value. The result
 -- value is used only in determining the next spline to sequence.
-data SplineT m f a b c = SplineT { unSplineT :: Var m a (Step (f b) c) }
+data SplineT f a b m c = SplineT { unSplineT :: Var m a (Step (f b) c) }
                        | SplineTConst c
 
--- | Unwrap a spline into a varying value.
+-- | Unwrap a spline into a value stream.
 runSplineT :: (Applicative m, Monad m, Monoid (f b))
-           => SplineT m f a b c -> Var m a (Step (f b) c)
+           => SplineT f a b m c -> Var m a (Step (f b) c)
 runSplineT (SplineT v) = v
 runSplineT (SplineTConst x) = pure $ pure x
 
 -- | 'Spline' is a specialized 'SplineT' that uses Event as its output
 -- container. This means that new values overwrite/replace old values due to
 -- Event's 'Last'-like monoid instance.
-type Spline m a b c = SplineT m Event a b c
+type Spline a b m c = SplineT Event a b m c
 
 -- | A spline is a functor by applying the function to the result.
-instance (Applicative m, Monad m) => Functor (SplineT m f a b) where
-    fmap f (SplineT v) = SplineT $ fmap (fmap f) v
+instance (Applicative m, Monad m) => Functor (SplineT f a b m) where
     fmap f (SplineTConst c)  = SplineTConst $ f c
+    fmap f (SplineT v) = SplineT $ fmap (fmap f) v
 
 -- | A spline is an applicative if its output type is a monoid. It
 -- responds to 'pure' by returning a spline that immediately returns the
@@ -105,7 +116,7 @@
 -- value (the function) to the right arguments eventual value. The
 -- output values will me combined with 'mappend'.
 instance (Monoid (f b), Applicative m, Monad m)
-    => Applicative (SplineT m f a b) where
+    => Applicative (SplineT f a b m) where
     pure = SplineTConst
     (SplineTConst f) <*> (SplineTConst x) = SplineTConst $ f x
     (SplineT vf) <*> (SplineTConst x) = SplineT $ fmap (fmap ($ x)) vf
@@ -115,7 +126,8 @@
 -- | A spline is monad if its output type is a monoid. A spline responds
 -- to bind by running until it produces an eventual value, then uses that
 -- value to run the next spline.
-instance (Monoid (f b), Applicative m, Monad m) => Monad (SplineT m f a b) where
+instance (Monoid (f b), Applicative m, Monad m) => Monad (SplineT f a b m) where
+    return = pure
     (SplineTConst x) >>= f = f x
     (SplineT v) >>= f = SplineT $ Var $ \i -> do
         (Step b e, v') <- runVar v i
@@ -123,25 +135,28 @@
             NoEvent -> return (Step b NoEvent, runSplineT $ SplineT v' >>= f)
             Event x -> runVar (runSplineT $ f x) i
 
+-- | A spline is a transformer and other monadic computations can be lifted
+-- int a spline.
+instance Monoid (f b) => MonadTrans (SplineT f a b) where
+    lift f = SplineT $ varM $ const $ liftM (Step mempty . Event) f
+
 -- | A spline can do IO if its underlying monad has a MonadIO instance. It
 -- takes the result of the IO action as its immediate return value and
 -- uses 'mempty' to generate an empty output value.
 instance (Monoid (f b), Functor m, Applicative m, MonadIO m)
-    => MonadIO (SplineT m f a b) where
-    liftIO f = SplineT $ Var $ \_ -> do
-        n <- (Step mempty . Event) <$> liftIO f
-        return (n, pure n)
+    => MonadIO (SplineT f a b m) where
+    liftIO = lift . liftIO
 
--- | Evaluates a spline to a varying value of its output type.
+-- | Evaluates a spline to a value stream of its output type.
 execSplineT :: (Applicative m, Monad m, Monoid (f b))
-            => SplineT m f a b c -> Var m a (f b)
+            => SplineT f a b m c -> Var m a (f b)
 execSplineT = (stepIter <$>) . runSplineT
 
 -- | Evaluates a spline to an event stream of its result. The resulting
--- varying value inhibits until the spline's domain is complete and then it
+-- value stream inhibits until the spline's domain is complete and then it
 -- produces events of the result type.
 evalSplineT :: (Applicative m, Monad m, Monoid (f b))
-            => SplineT m f a b c -> Var m a (Event c)
+            => SplineT f a b m c -> Var m a (Event c)
 evalSplineT = (stepResult <$>) . runSplineT
 
 -- | Create a spline using an event stream. The spline will run until the
@@ -149,47 +164,83 @@
 -- output value. In the case the stream inhibits before producing
 -- a value the default value is used. The spline's result value is the last
 -- output value.
-spline :: (Applicative m, Monad m) => b -> Var m a (Event b) -> Spline m a b b
+spline :: (Applicative m, Monad m) => b -> Var m a (Event b) -> Spline a b m b
 spline x ve = SplineT $ Var $ \a -> do
     (ex, ve') <- runVar ve a
     case ex of
         NoEvent  -> let n = Step (Event x) (Event x) in return (n, pure n)
         Event x' -> return (Step (Event x') NoEvent, runSplineT $ spline x' ve')
 
--- | Unwrap a spline into a varying value. This is an alias of
--- 'runSplineT'.
-runSpline :: (Applicative m, Monad m) => Spline m a b c -> Var m a (Step (Event b) c)
-runSpline = runSplineT
-
--- | Using a default start value, evaluate the spline to a varying value.
+-- | Using a default start value, evaluate the spline to a value stream.
 -- A spline is only defined over a finite domain so we must supply a default
 -- value to use before the spline produces its first output value.
-execSpline :: (Applicative m, Monad m) => b -> Spline m a b c -> Var m a b
+execSpline :: (Applicative m, Monad m) => b -> Spline a b m c -> Var m a b
 execSpline x (SplineTConst _) = pure x
 execSpline x s = execSplineT s ~> foldStream (\_ y -> y) x
 
--- | Create a spline from a varying value and an event stream. The spline
--- uses the varying value as its output value. The spline will run until
+-- | Create a spline from a value stream and an event stream. The spline
+-- uses the value stream as its output value. The spline will run until
 -- the event stream produces a value, at that point the last output
--- value and the event value are used in a merge function to produce the
--- spline's result value.
-varyUntilEvent :: (Applicative m, Monad m)
-               => Var m a b -> Var m a (Event c) -> (b -> c -> d)
-               -> Spline m a b d
-varyUntilEvent v ve f = SplineT $ Var $ \a -> do
-    (b, v') <- runVar v a
-    (ec, ve') <- runVar ve a
-    case ec of
-        NoEvent -> return (Step (Event b) NoEvent,
-                           runSplineT $ varyUntilEvent v' ve' f)
-        Event c -> let n = Step (Event b) (Event $ f b c)
-                   in return (n, pure n)
+-- value and the event value are tupled and returned as the spline's result
+-- value.
+untilEvent :: (Applicative m, Monad m)
+           => Var m a b -> Var m a (Event c)
+           -> Spline a b m (b,c)
+untilEvent v ve = SplineT $ t ~> var (uncurry f)
+    where t = (,) <$> v <*> ve
+          f b ec = case ec of
+                       NoEvent -> Step (Event b) NoEvent
+                       Event c -> Step (Event b) (Event (b, c))
 
+-- | Run two splines concurrently and return the result of the SplineT that
+-- concludes first. If they conclude at the same time the result is taken from
+-- the spline on the left.
+race :: (Applicative m, Monad m, Monoid (f u))
+          => SplineT f i u m a -> SplineT f i u m a -> SplineT f i u m a
+race (SplineTConst a) s =
+    race (SplineT $ pure $ Step mempty $ Event a) s
+race s (SplineTConst b) =
+    race s (SplineT $ pure $ Step mempty $ Event b)
+race (SplineT va) (SplineT vb) = SplineT $ Var $ \i -> do
+    (Step ua ea, va') <- runVar va i
+    (Step ub eb, vb') <- runVar vb i
+    case (ea,eb) of
+        (Event _,_) -> return (Step (ua <> ub) ea, va')
+        (_,Event _) -> return (Step (ua <> ub) eb, vb')
+        (_,_)       -> return (Step (ua <> ub) NoEvent,
+                               runSplineT $ race (SplineT va') (SplineT vb'))
+
+-- | Run a list of splines concurrently. Restart individual splines whenever
+-- they conclude in a value. Return a list of the most recent result values once
+-- the control spline concludes.
+mix :: (Applicative m, Monad m, Monoid (f b))
+    => [Maybe c -> SplineT f a b m c] -> SplineT f a b m ()
+    -> SplineT f a b m [Maybe c]
+mix gs = go gs es $ zipWith ($) gs xs
+    where es = replicate n NoEvent
+          xs = replicate n Nothing
+          n  = length gs
+          go fs evs guis egui = SplineT $ Var $ \a -> do
+            let step (ecs, fb, vs) (f, ec, g) = do
+                    (Step fb' ec', v) <- runVar (runSplineT g) a
+                    let ec'' = ec <> ec'
+                        fb'' = fb <> fb'
+                        v'   = case ec' of
+                                   NoEvent -> v
+                                   Event c -> runSplineT $ f $ Just c
+                    return (ecs ++ [ec''], fb'', vs ++ [SplineT v'])
+            (ecs, fb, guis') <- foldM step ([],mempty,[]) (zip3 fs evs guis)
+            (Step fb' ec, v) <- runVar (runSplineT egui) a
+            let fb'' = fb <> fb'
+                ec' = map toMaybe ecs <$ ec
+            return (Step fb'' ec',
+                    runSplineT $ go fs ecs guis' $ SplineT v)
+
 -- | Capture the spline's latest output value and tuple it with the
 -- spline's result value. This is helpful when you want to sample the last
 -- output value in order to determine the next spline to sequence.
 capture :: (Applicative m, Monad m, Monoid (f b), Eq (f b))
-        => SplineT m f a b c -> SplineT m f a b (f b, c)
+        => SplineT f a b m c -> SplineT f a b m (f b, c)
 capture (SplineTConst x) = SplineTConst (mempty, x)
 capture (SplineT v) = capture' mempty v
     where capture' mb v' = SplineT $ Var $ \a -> do
@@ -197,3 +248,9 @@
               let mb' = if fb == mempty then mb else fb
                   ec' = (mb',) <$> ec
               return (Step fb ec', runSplineT $ capture' mb' v'')
+
+-- | Map the output value of a spline.
+mapOutput :: (Functor f, Monoid (f t), Applicative m, Monad m)
+          => Var m a (f b -> f t) -> SplineT f a b m c -> SplineT f a t m c
+mapOutput _ (SplineTConst c) = SplineTConst c
+mapOutput vf (SplineT vx) = SplineT $ toIter <$> vf <*> vx
diff --git a/src/Control/Varying/Time.hs b/src/Control/Varying/Time.hs
--- a/src/Control/Varying/Time.hs
+++ b/src/Control/Varying/Time.hs
@@ -6,15 +6,15 @@
 module Control.Varying.Time where
 
 import Control.Varying.Core
-import Control.Varying.Event hiding (after, before)
+import Control.Varying.Event
 import Control.Applicative
 import Data.Time.Clock
 
--- | Produces "time" deltas using 'getCurrentTime' and 'diffUTCTime'.
+-- | Produces time deltas using 'getCurrentTime' and 'diffUTCTime'.
 deltaUTC :: Fractional t => Var IO b t
 deltaUTC = delta getCurrentTime (\a b -> realToFrac $ diffUTCTime a b)
 
--- | Produces "time" deltas using a monadic computation and a difference
+-- | Produces time deltas using a monadic computation and a difference
 -- function.
 delta :: (Num t, Fractional t, Applicative m, Monad m)
       => m a -> (a -> a -> t) -> Var m b t
@@ -32,16 +32,16 @@
 -- 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 :: (Applicative m, Monad m, Num t, Ord t) => t -> Var m t (Event ())
-before t = Var $ \dt -> do
+before t = Var $ \dt -> return $
     if t - dt >= 0
-    then return (Event (), before $ t - dt)
-    else return (NoEvent, never)
+    then (Event (), before $ t - dt)
+    else (NoEvent, never)
 
 -- | 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 :: (Applicative m, Monad m, Num t, Ord t) => t -> Var m t (Event ())
-after t = Var $ \dt -> do
+after t = Var $ \dt -> return $
     if t - dt <= 0
-    then return (Event (), pure $ Event ())
-    else return (NoEvent, after $ t - dt)
+    then (Event (), pure $ Event ())
+    else (NoEvent, after $ t - dt)
diff --git a/src/Control/Varying/Tween.hs b/src/Control/Varying/Tween.hs
--- a/src/Control/Varying/Tween.hs
+++ b/src/Control/Varying/Tween.hs
@@ -22,39 +22,30 @@
     -- $creation
     tween,
     constant,
-    -- * Tweening with splines
-    -- $splines
-    tweenTo,
     -- * Interpolation functions
     -- $lerping
     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
+    -- $writing
     Tween,
     Easing
 ) where
 
 import Control.Varying.Core
-import Control.Varying.Event hiding (after, before)
+import Control.Varying.Event
 import Control.Varying.Spline
 import Control.Varying.Time
 import Control.Arrow
@@ -76,10 +67,6 @@
 easeOutQuad :: Num t => Easing t
 easeOutQuad c t b =  (-c) * (t * (t - 2)) + b
 
--- | Ease in and out quadratic.
-easeInOutQuad :: (Ord t, Fractional t) => Easing t
-easeInOutQuad = easeInOut easeInQuad easeOutQuad
-
 -- | Ease in cubic.
 easeInCubic :: Num t => Easing t
 easeInCubic c t b =  c * t*t*t + b
@@ -88,14 +75,6 @@
 easeOutCubic :: Num t => Easing t
 easeOutCubic c t b =  let t' = t - 1 in c * (t'*t'*t' + 1) + b
 
--- | Ease in and out cubic.
-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
@@ -130,10 +109,6 @@
 easeOutExpo :: Floating t => Easing t
 easeOutExpo c t b =  let e = -10 * t in c * (-(2**e) + 1) + b
 
--- | Ease in and out exponential.
-easeInOutExpo :: (Ord t, Floating t) => Easing t
-easeInOutExpo = easeInOut easeInExpo easeOutExpo
-
 -- | Ease in circular.
 easeInCirc :: Floating t => Easing t
 easeInCirc c t b = let s = sqrt (1 - t*t) in -c * (s - 1) + b
@@ -144,96 +119,61 @@
                         s  = sqrt (1 - t'*t')
                     in c * s + b
 
--- | Ease in and out circular.
-easeInOutCirc :: (Ord t, Floating t) => Easing t
-easeInOutCirc = easeInOut easeInCirc easeOutCirc
-
--- | Ease in and out using the given easing equations.
-easeInOut :: (Ord t, Num t, Fractional t) => Easing t -> Easing t -> Easing t
-easeInOut ein eout c t b = if t >= 0.5 then ein c t b else eout c t b
-
 -- | Ease linear.
 linear :: Num t => Easing t
 linear c t b = c * t + b
 
 --------------------------------------------------------------------------------
 -- $creation
---
 -- The most direct route toward 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.
+-- along with an interpolation function such as 'easeInExpo'. For example,
+-- @tween easeInOutExpo 0 100 10@, this will create a spline that produces a
+-- number interpolated from 0 to 100 over 10 seconds. At the end of the
+-- tween the spline will return the result value.
 --------------------------------------------------------------------------------
 
--- | 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:
+-- | Creates a spline that produces a value interpolated between a start and
+-- end value using an easing equation ('Easing') over a duration.  The
+-- resulting spline will take a time delta as input. For example:
 --
 -- @
--- testWhile_ isEvent v
+-- testWhile_ isEvent (deltaUTC ~> v)
 --    where v :: Var IO a (Event Double)
---          v = deltaUTC ~> tween easeOutExpo 0 100 5
+--          v = execSpline 0 $ tween easeOutExpo 0 100 5
 -- @
 --
 -- 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 :: (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)
-    t <- timeAsPercentageOf dur -< dt
-    -- Emitted event
-    e <- before dur -< dt
-    -- Total change in value
-    let c = end - start
-        b = start
-        x = f c t b
-    -- Tag the event with the value.
-    returnA -< x <$ e
+      => Easing t -> t -> t -> t -> Spline t t m t
+tween f start end dur = spline start $ timeAsPercentageOf dur ~> var g
+    where g t = let c = end - start
+                    b = start
+                    x = f c t b
+                in if t <= 1.0 then Event x else NoEvent
 
--- Creates a tween that performs no interpolation over the duration.
+-- | 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
+         => a -> t -> Spline t a m a
+constant value duration = spline value $ use value $ before duration
 
+-- | Varies 0.0 to 1.0 linearly for duration `t` and 1.0 after `t`.
+timeAsPercentageOf :: (Applicative m, Monad m, Ord t, Num t, Fractional t)
+                   => t -> Var m t t
+timeAsPercentageOf t = (\t' -> min 1 (t' / t)) <$> accumulate (+) 0
+
 --------------------------------------------------------------------------------
--- $splines
--- If you plan on doing a lot of tweening it's probably easiest to build up
--- your tweens as splines using do-notation.
--- A spline in this context is a numeric computation that is "smooth" over some
--- domain. It is defined in a piecewise manner by sequencing other splines
--- together using do-notation.
--- You can then run the spline, transforming it back into a continuous
--- varying value.
+-- $writing
+-- To create your own tweens just write a function that takes a start
+-- value, end value and a duration and return an event stream.
 --
 -- @
--- thereAndBack = execSpline 0 $ do
---   x <- tweenTo easeOutExpo 0 100 1
---   tweenTo easeOutExpo x 0 1
+-- tweenInOutExpo s e d = execSpline s $ do
+--     x <- tween easeInExpo s e (d/2)
+--     tween easeOutExpo x e (d/2)
 -- @
 --------------------------------------------------------------------------------
--- |
-tweenTo :: (Applicative m, Monad m, Fractional t, Ord t)
-        => Easing t -> t -> t -> t -> Spline m t t t
-tweenTo f start end dur = spline start $ tween f start end dur
-
--- | Varies 0.0 to 1.0 linearly for duration `t` and 1.0 after `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)
-
 -- | 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
diff --git a/src/Example.hs b/src/Example.hs
--- a/src/Example.hs
+++ b/src/Example.hs
@@ -1,68 +1,62 @@
 module Main where
 
 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.
-data Point = Point { x :: Float
-                   , y :: Float
+data Point = Point { px :: Float
+                   , py :: Float
                    } deriving (Show, Eq)
 
--- | Our Point value that varies over time continuously in x and y.
-backAndForth :: Var IO a Point
-backAndForth =
-    -- Here we use Applicative to construct a varying Point that takes time
-    -- as an input.
-    (Point <$> tweenx <*> tweeny)
-        -- Here we feed the varying Point a time signal using the 'plug left'
-        -- function. We could similarly use the 'plug right' (~>) function
-        -- and put the time signal before the Point. This is needed because the
-        -- tweens take time as an input.
-        <~ time
-
--- An exponential tween back and forth from 0 to 100 over 2 seconds.
-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
-    -- a tween's full type will be
-    -- (Ord t, Fractional t, Monad m) => Var m t (Event t).
-     tween easeOutExpo 0 100 1
-         -- We can chain another tween back to the starting position using
-         -- `andThenE`, which will sample the first tween until it ends and then
-         -- switch to sampling the next tween.
-         `andThenE`
-             -- Tween back to the starting position.
-             tween easeOutExpo 100 0 1
-                 -- At this point our resulting sample values will still have the
-                 -- type (Event Float). The tween as a whole will be an event
-                 -- stream. The tween also only runs back and forth once. We'd
-                 -- like the tween to loop forever so that our point cycles back
-                 -- and forth between 0 and 100 indefinitely.
-                 -- We can accomplish this with recursion and the `andThen`
-                 -- combinator, which samples an event stream until it
-                 -- inhibits and then switches to a normal value stream (a
-                 -- varying value). Put succinctly, it disolves our events into
-                 -- values.
-                 `andThen` tweenx
+-- An exponential tween back and forth from 0 to 100 over 2 seconds that
+-- loops forever. This spline takes float values of delta time as input,
+-- outputs the current x value at every step and would result in () if it
+-- terminated.
+tweenx :: (Applicative m, Monad m) => Spline Float Float m ()
+tweenx = do
+    -- Tween from 0 to 100 over 1 second
+    x <- tween easeOutExpo 0 100 1
+    -- Chain another tween back to the starting position
+    _ <- tween easeOutExpo x 0 1
+    -- Loop forever
+    tweenx
 
--- A quadratic tween back and forth from 0 to 100 over 2 seconds.
-tweeny :: (Applicative m, Monad m) => Var m Float Float
-tweeny =
-    tween easeOutQuad 0 100 1 `andThenE` tween easeOutQuad 100 0 1 `andThen` tweeny
+-- A quadratic tween back and forth from 0 to 100 over 2 seconds that never
+-- ends.
+tweeny :: (Applicative m, Monad m) => Spline Float Float m ()
+tweeny = do
+    y <- tween easeOutQuad 0 100 1
+    _ <- tween easeOutQuad y 0 1
+    tweeny
 
--- Our time signal.
+-- Our time signal that provides delta time samples.
 time :: Var IO a Float
 time = deltaUTC
 
+-- | Our Point value that varies over time continuously in x and y.
+backAndForth :: Var IO a Point
+backAndForth =
+    -- Turn our splines back into continuous value streams. We must provide
+    -- a starting value since splines are not guaranteed to be defined at
+    -- their edges.
+    let x = execSpline 0 tweenx
+        y = execSpline 0 tweeny
+    in
+    -- Construct a varying Point that takes time as an input.
+    (Point <$> x <*> y)
+        -- Stream in a time signal using the 'plug left' combinator.
+        -- We could similarly use the 'plug right' (~>) function
+        -- and put the time signal before the construction above. This is needed
+        -- because the tween streams take time as an input.
+        <~ time
+
 main :: IO ()
 main = do
     putStrLn "Varying Values"
     loop backAndForth
         where loop :: Var IO () Point -> IO ()
               loop v = do (point, vNext) <- runVar v ()
-                          printf "\nPoint %03.1f %03.1f" (x point) (y point)
+                          printf "\nPoint %03.1f %03.1f" (px point) (py point)
                           loop vNext
 
diff --git a/varying.cabal b/varying.cabal
--- a/varying.cabal
+++ b/varying.cabal
@@ -10,15 +10,15 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.1.5.0
+version:             0.2.0.0
 
 -- A short (one-line) description of the package.
-synopsis:            FRP through varying values and monadic splines.
+synopsis:            FRP through value streams and monadic splines.
 
 -- A longer description of the package.
 description:         Varying is a FRP implentation aimed at providing a
-                     simple way to describe values that change over some domain.
-                     It allows monadic, applicative or arrow notation and has
+                     simple way to describe values that change over a domain.
+                     It allows monadic, applicative and arrow notation and has
                      convenience functions for tweening.
 
 -- URL for the project homepage or repository.
