diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -4,17 +4,20 @@
 import Control.Applicative
 import Text.Printf
 import Data.Functor.Identity
+import Data.Time.Clock
 
 -- | A simple 2d point type.
 data Point = Point { px :: Float
                    , py :: Float
                    } deriving (Show, Eq)
 
+newtype Delta = Delta { unDelta :: Float }
+
 -- 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) => SplineT Float Float m ()
+tweenx :: (Applicative m, Monad m) => SplineT Float Float m Float
 tweenx = do
     -- Tween from 0 to 100 over 1 second
     x <- tween easeOutExpo 0 100 1
@@ -25,24 +28,24 @@
 
 -- A quadratic tween back and forth from 0 to 100 over 2 seconds that never
 -- ends.
-tweeny :: (Applicative m, Monad m) => SplineT Float Float m ()
+tweeny :: (Applicative m, Monad m) => SplineT Float Float m Float
 tweeny = do
     y <- tween easeOutQuad 0 100 1
     _ <- tween easeOutQuad y 0 1
     tweeny
 
--- Our time signal that provides delta time samples.
-time :: VarT IO a Float
-time = deltaUTC
+-- Our time signal counts input delta time samples.
+time :: Monad m => VarT m Delta Float
+time = var unDelta
 
 -- | Our Point value that varies over time continuously in x and y.
-backAndForth :: VarT IO a Point
+backAndForth :: Monad m => VarT m Delta Point
 backAndForth =
     -- Turn our splines into continuous output streams. We must provide
     -- a starting value since splines are not guaranteed to be defined at
     -- their edges.
-    let x = outputStream 0 tweenx
-        y = outputStream 0 tweeny
+    let x = outputStream tweenx 0
+        y = outputStream tweeny 0
     in
     -- Construct a varying Point that takes time as an input.
     (Point <$> x <*> y)
@@ -57,10 +60,12 @@
     putStrLn "An example of value streams using the varying library."
     putStrLn "Enter a newline to continue, quit with ctrl+c"
     _ <- getLine
+    utc0 <- getCurrentTime
 
-    loop backAndForth
-        where loop :: VarT IO () Point -> IO ()
-              loop v = do (point, vNext) <- runVarT v ()
-                          printf "\nPoint %03.1f %03.1f" (px point) (py point)
-                          loop vNext
+    loop backAndForth utc0
+        where loop v utc1 = do utc2 <- getCurrentTime
+                               let dt = realToFrac $ diffUTCTime utc2 utc1
+                               (point, vNext) <- runVarT v $ Delta dt
+                               printf "\nPoint %03.1f %03.1f" (px point) (py point)
+                               loop vNext utc2
 
diff --git a/bench/Main.hs b/bench/Main.hs
new file mode 100644
--- /dev/null
+++ b/bench/Main.hs
@@ -0,0 +1,24 @@
+import Control.Varying
+import Criterion.Main
+import Debug.Trace
+
+main :: IO ()
+main = do
+    let v :: Var Int Int
+        v = var (+1)
+        run v a = fst <$> runVarT v a
+    defaultMain $ [ bgroup "runVarT" [ bench "1" $ nf (run $ chain 1) 0
+                                     , bench "2" $ nf (run $ chain 2) 0
+                                     , bench "4" $ nf (run $ chain 4) 0
+                                     , bench "8" $ nf (run $ chain 8) 0
+                                     , bench "16" $ nf (run $ chain 16) 0
+                                     , bench "32" $ nf (run $ chain 32) 0
+                                     , bench "64" $ nf (run $ chain 64) 0
+                                     , bench "128" $ nf (run $ chain 128) 0
+                                     ]
+                  ]
+    return ()
+
+chain :: Int -> Var Int Int
+chain n = seq x x
+  where x = foldl (~>) (var (+1)) $ take (n - 1) $ cycle [var (+1)]
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -11,4 +11,7 @@
 0.3.1.0 - added stepMany, eitherE
 
 0.4.0.0 - Var and Spline are now parameterized with Identity, removed mix, changed
-          the behavior of race, added untilEvent variants, added tests.
+          the behavior of race, added untilEvent variants, added tests
+
+0.5.0.0 - changed stepMany to remove Monoid requirement, added raceMany, added 
+          anyE, more tests and SplineT obeys Applicative and Monad laws
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
@@ -1,3 +1,4 @@
+{-# LANGUAGE GADTs #-}
 -- |
 --   Module:     Control.Varying.Core
 --   Copyright:  (c) 2015 Schell Scivally
@@ -16,6 +17,7 @@
     VarT(..),
     -- * Creating value streams
     -- $creation
+    done,
     var,
     varM,
     mkState,
@@ -23,23 +25,17 @@
     -- $composition
     (<~),
     (~>),
+    (<<<),
+    (>>>),
     -- * Adjusting and accumulating
     delay,
     accumulate,
     -- * Sampling value streams (running and other entry points)
     -- $running
-    evalVar,
-    execVar,
-    loopVar,
-    loopVar_,
-    whileVar,
-    whileVar_,
+    runVarT,
     scanVar,
     stepMany,
-    -- * Testing value streams
-    testVar,
-    testVar_,
-    testWhile_,
+    -- * Tracing value streams in flight
     vtrace,
     vstrace,
     vftrace,
@@ -48,7 +44,7 @@
 import Prelude hiding (id, (.))
 import Control.Arrow
 import Control.Category
-import Control.Monad 
+import Control.Monad
 import Control.Applicative
 import Data.Monoid
 import Data.Functor.Identity
@@ -89,6 +85,10 @@
 var :: Applicative m => (a -> b) -> VarT m a b
 var f = VarT $ \a -> pure (f a, var f)
 
+-- | Lift a constant value into a stream.
+done :: Applicative m => b -> VarT m a b
+done = Done
+
 -- | Lift a monadic computation into a stream.
 varM :: Monad m => (a -> m b) -> VarT m a b
 varM f = VarT $ \a -> do
@@ -105,57 +105,25 @@
   return (b', mkState f s')
 --------------------------------------------------------------------------------
 -- $running
--- The easiest way to sample a stream is to run it in the desired monad with
+-- To sample a stream simply run it in the desired monad with
 -- 'runVarT'. This will produce a sample value and a new stream.
 --
 -- > do (sample, v') <- runVarT v inputValue
---
--- Much like Control.Monad.State there are other entry points for running
--- value streams like 'evalVar', 'execVar'. There are also extra control
--- structures such as 'loopVar' and 'whileVar'.
---------------------------------------------------------------------------------
--- | Iterate a stream once and return the sample value.
-evalVar :: Functor m => VarT m a b -> a -> m b
-evalVar v a = fst <$> runVarT v a
 
--- | Iterate a stream once and return the next stream.
-execVar :: Functor m => VarT m a b -> a -> m (VarT m a b)
-execVar v a = snd <$> runVarT v a
-
--- | Loop over a stream that takes no input value.
-loopVar_ :: (Functor m, Monad m) => VarT m () a -> m ()
-loopVar_ v = execVar v () >>= loopVar_
-
--- | Loop over a stream that produces its own next input value.
-loopVar :: Monad m => a -> VarT m a a -> m a
-loopVar a v = runVarT v a >>= uncurry loopVar
-
--- | Iterate a stream that requires no input until the given predicate fails.
-whileVar_ :: Monad m => (a -> Bool) -> VarT m () a -> m a
-whileVar_ f v = do
-   (a, v') <- runVarT v ()
-   if f a then whileVar_ f v' else return a
-
--- | Iterate a stream that produces its own next input value until the given
--- predicate fails.
-whileVar :: Monad m
-         => (a -> Bool) -- ^ The predicate to evaluate samples.
-         -> a -- ^ The initial input/sample value.
-         -> VarT m a a -- ^ The stream to iterate
-         -> m a -- ^ The last sample
-whileVar f a v = if f a
-                 then runVarT v a >>= uncurry (whileVar f)
-                 else return a
+--------------------------------------------------------------------------------
+runVarT :: Monad m => VarT m a b -> a -> m (b, VarT m a b)
+runVarT (Done b) _ = return (b, Done b)
+runVarT (VarT v) a = v a
 
--- | Iterate a stream using a list of input until all input is consumed and
--- output the result.
-stepMany :: (Monad m, Functor m, Monoid a) => [a] -> VarT m a b -> m (b, VarT m a b)
-stepMany ([e]) y = runVarT y e
-stepMany (e:es) y = execVar y e >>= stepMany es
-stepMany []     y = runVarT y mempty
+-- | Iterate a stream over a list of input until all input is consumed,
+-- then iterate the stream using one single input. Returns the resulting
+-- output value and the new stream.
+stepMany :: (Monad m, Functor m) => VarT m a b -> [a] -> a -> m (b, VarT m a b)
+stepMany v [] e = runVarT v e
+stepMany v (e:es) x = snd <$> runVarT v e >>= \v1 -> stepMany v1 es x
 
--- | Run the stream over the input values, gathering the output values in a 
--- list. 
+-- | Run the stream over the input values, gathering the output values in a
+-- list.
 scanVar :: (Applicative m, Monad m) => VarT m a b -> [a] -> m [b]
 scanVar v = liftM snd . foldM f (v,[])
     where f (v', outs) a = do (b, v'') <- runVarT v' a
@@ -177,28 +145,6 @@
 -- This is very useful for debugging graphs of streams.
 vftrace :: Applicative a => (b -> String) -> VarT a b b
 vftrace f = var $ \b -> trace (f b) b
-
--- | A utility function for testing streams that don't require input. Runs
--- a stream printing each sample until the given predicate fails.
-testWhile_ :: Show a => (a -> Bool) -> VarT IO () a -> IO ()
-testWhile_ f v = do
-    (a, v') <- runVarT v ()
-    when (f a) $ print a >> testWhile_ f v'
-
--- | A utility function for testing streams that require input. The input
--- must have a 'Read' instance. Use this in GHCI to step through your streams
--- by typing the input and hitting `return`.
-testVar :: (Read a, Show b) => VarT IO a b -> IO ()
-testVar v = loopVar_ $ varM (const $ putStrLn "input: ")
-                    ~> varM (const getLine)
-                    ~> var read
-                    ~> v
-                    ~> varM print
-
--- | A utility function for testing streams that don't require input. Use
--- this in GHCI to step through your streams using the `return` key.
-testVar_ :: Show b => VarT IO () b -> IO ()
-testVar_ v = loopVar_ $ pure () ~> v ~> varM print ~> varM (const getLine)
 --------------------------------------------------------------------------------
 -- Adjusting and accumulating
 --------------------------------------------------------------------------------
@@ -220,26 +166,18 @@
                                      return (b', go a' v'')
 --------------------------------------------------------------------------------
 -- $composition
--- 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.
+-- You can compose value streams together using Arrow's '>>>' and '<<<' or the
+-- synonyms '~>' and '<~'. The "right plug" ('>>>' and '~>') 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 => VarT m b c -> VarT m a b -> VarT m a c
-(<~) = flip (~>)
-infixl 1 <~
-
--- | Connects two streams by chaining the first's output into the input of the
--- second. This is the defacto stream composition method and in fact '.' is an
--- alias of '<~', which is just '~>' flipped.
 (~>) :: Monad m => VarT m a b -> VarT m b c -> VarT m a c
-(~>) v1 v2 = VarT $ \a -> do
-    (b, v1') <- runVarT v1 a
-    (c, v2') <- runVarT v2 b
-    return (c, v1' ~> v2')
-infixr 1 ~>
+(~>) = (>>>)
+
+(<~) :: Monad m => VarT m b c -> VarT m a b -> VarT m a c
+(<~) = (<<<)
 --------------------------------------------------------------------------------
 -- Typeclass instances
 --------------------------------------------------------------------------------
@@ -248,29 +186,32 @@
 -- >  fmap (*3) $ accumulate (+) 0
 -- Will sum input values and then multiply the sum by 3.
 instance (Applicative m, Monad m) => Functor (VarT m b) where
-    fmap f' v = v ~> var f'
+  fmap f (Done x) = Done $ f x
+  fmap f v = v >>> var f
 
 -- | A very simple category instance.
 --
 -- @
 --   id = var id
---   f . g = g ~> f
+--   f . g = g >>> f
 -- @
 -- or
 --
--- >  f . g = f <~ g
+-- >  f . g = f <<< g
 --
--- It is preferable for consistency (and readability) to use 'plug left' ('<~')
--- and 'plug right' ('~>') instead of ('.') where possible.
+-- It is preferable for consistency (and readability) to use 'plug left' ('<<<')
+-- and 'plug right' ('>>>') instead of ('.') where possible.
 instance (Applicative m, Monad m) => Category (VarT m) where
     id = var id
-    f . g = g ~> f
+    f0 . g0 = VarT $ \a -> do (b, g) <- runVarT g0 a
+                              (c, f) <- runVarT f0 b
+                              return (c, f . g)
 
 -- | Streams are applicative.
 --
 -- >  (,) <$> pure True <*> var "Applicative"
 instance (Applicative m, Monad m) => Applicative (VarT m a) where
-    pure = var . const
+    pure = done
     vf <*> va = VarT $ \a -> do (f, vf') <- runVarT vf a
                                 (b, va') <- runVarT va a
                                 return (f b, vf' <*> va')
@@ -300,7 +241,7 @@
 
 -- | Streams can be written as numbers.
 --
--- >  let v = 1 ~> accumulate (+) 0
+-- >  let v = 1 >>> accumulate (+) 0
 -- which will sum the natural numbers.
 instance (Applicative m, Monad m, Num b) => Num (VarT m a b) where
     (+) = liftA2 (+)
@@ -312,7 +253,7 @@
 
 -- | Streams can be written as floats.
 --
--- >  let v = pi ~> accumulate (*) 0.0
+-- >  let v = pi >>> accumulate (*) 0.0
 -- which will attempt (and succeed) to multiply pi by zero every step.
 instance (Applicative m, Monad m, Floating b) => Floating (VarT m a b) where
     pi = pure pi
@@ -324,7 +265,7 @@
 
 -- | Streams can be written as fractionals.
 --
--- >  let v = 2.5 ~> accumulate (+) 0
+-- >  let v = 2.5 >>> accumulate (+) 0
 -- which will add 2.5 each step.
 instance (Applicative m, Monad m, Fractional b) => Fractional (VarT m a b) where
     (/) = liftA2 (/)
@@ -337,13 +278,15 @@
 -- 'VarT'.
 type Var a b = VarT Identity a b
 
--- | A value stream is a structure that contains a value that changes over some 
+-- | A value stream is a structure that contains a value that changes over some
 -- input. It's a kind of Mealy machine (an automaton) with effects. Using
--- 'runVarT' with an input value of type 'a' yields a "step", which is a value 
+-- 'runVarT' with an input value of type 'a' yields a "step", which is a value
 -- of type 'b' and a new 'VarT' for yielding the next value.
-data VarT m a b =
-     VarT { runVarT :: a -> m (b, VarT m a b)
-            -- ^ Given an input value, return a computation that effectfully 
-            -- produces an output value and a new stream for producing the next 
-            -- sample.
-          }
+data VarT m a b where
+  Done :: b -> VarT m a b
+          -- ^ Given a value, return a computation that yields a constant value
+          -- forever. You can also do this with the function 'done'.
+  VarT :: (a -> m (b, VarT m a b)) -> VarT m a b
+          -- ^ Given an input value, return a computation that effectfully
+          -- produces an output value and a new stream for producing the next
+          -- sample.
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
@@ -29,6 +29,7 @@
     startingWith, startWith,
     -- * Using multiple streams
     eitherE,
+    anyE,
     -- * List-like operations on event streams
     filterE,
     takeE,
@@ -38,6 +39,7 @@
     always,
     never,
     -- * Switching
+    andThenWith,
     switchByMode,
     -- * Bubbling
     onlyWhen,
@@ -49,6 +51,7 @@
 import Control.Applicative
 import Control.Monad
 import Data.Monoid
+import Data.Foldable (foldl')
 --------------------------------------------------------------------------------
 -- Transforming event values into usable values
 --------------------------------------------------------------------------------
@@ -122,7 +125,7 @@
 -- 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
+-- time >>> after 3 >>> startingWith 0
 -- @
 startingWith, startWith :: (Applicative m, Monad m) => a -> VarT m (Event a) a
 startingWith = startWith
@@ -151,7 +154,7 @@
 -- | Inhibit all events that don't pass the predicate.
 filterE :: (Applicative m, Monad m)
         => (b -> Bool) -> VarT m a (Event b) -> VarT m a (Event b)
-filterE p v = v ~> var check
+filterE p v = v >>> var check
     where check (Event b) = if p b then Event b else NoEvent
           check _ = NoEvent
 --------------------------------------------------------------------------------
@@ -160,13 +163,23 @@
 -- | If the left event stream produces a value, wrap the value in 'Left' and
 -- produce that value, else if the right event stream produces a value,
 -- wrap the value in 'Right' and produce that value, else inhibit.
-eitherE :: (Applicative m, Monad m) 
-        => VarT m a (Event b) -> VarT m a (Event c) 
+eitherE :: (Applicative m, Monad m)
+        => VarT m a (Event b) -> VarT m a (Event c)
         -> VarT m a (Event (Either b c))
 eitherE vb vc = f <$> vb <*> vc
     where f (Event b) _ = Event $ Left b
           f _ (Event c) = Event $ Right c
           f _ _ = NoEvent
+
+-- | Combine two event streams and produce an event any time either stream
+-- produces. In the case that both streams produce, this produces the event of
+-- the left stream.
+anyE :: Monad m => [VarT m a (Event b)] -> VarT m a (Event b)
+anyE [] = never
+anyE vs = VarT $ \a -> do
+  outs <- mapM (`runVarT` a) vs
+  let f (eb, vs1) (eb1, v) = (msum [eb, eb1], vs1 ++ [v])
+  return (anyE <$> foldl' f (NoEvent, []) outs)
 --------------------------------------------------------------------------------
 -- Primitive event streams
 --------------------------------------------------------------------------------
@@ -192,7 +205,7 @@
 switchByMode switch f = VarT $ \a -> do
     (b, _) <- runVarT switch a
     (_, v) <- runVarT (f b) a
-    runVarT (switchOnUnique v $ switch ~> onUnique) a
+    runVarT (switchOnUnique v $ switch >>> onUnique) a
         where switchOnUnique v sv = VarT $ \a -> do
                   (eb, sv') <- runVarT sv a
                   (c', v')  <- runVarT (vOf eb) a
@@ -200,6 +213,15 @@
                       where vOf eb = case eb of
                                          NoEvent -> v
                                          Event b -> f b
+
+andThenWith :: (Applicative m, Monad m)
+            => VarT m a (Event b) -> (Event b -> VarT m a (Event b)) -> VarT m a (Event b)
+v `andThenWith` f = run v NoEvent
+  where run v1 eb = VarT $ \a -> do
+          (eb1, v2) <- runVarT v1 a
+          case eb1 of
+            NoEvent -> runVarT (f eb) a
+            _       -> return (eb1, run v2 eb1)
 --------------------------------------------------------------------------------
 -- Bubbling
 --------------------------------------------------------------------------------
@@ -211,7 +233,7 @@
          -> (a -> Bool) -- ^ 'f' - The predicate to run on 'v''s input values.
          -> VarT m a (Event b)
 onlyWhen v f = v `onlyWhenE` hot
-    where hot = var id ~> onWhen f
+    where hot = var id >>> onWhen f
 
 -- | Produce events of a value stream 'v' only when an event stream 'h'
 -- produces an event.
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
@@ -26,150 +26,117 @@
     SplineT(..),
     runSplineT,
     scanSpline,
-    fromEvents,
     outputStream,
     resultStream,
+    -- * Combinators
     step,
-    -- * Combinators 
+    effect,
+    fromEvent,
     untilEvent,
     untilEvent_,
     _untilEvent,
-    pair,
+    _untilEvent_,
     race,
+    raceMany,
+    merge,
     capture,
     mapOutput,
     adjustInput,
-    -- * Step
-    Step(..),
 ) where
 
 import Control.Varying.Core
 import Control.Varying.Event
-import Control.Monad.IO.Class
-import Control.Monad.Trans.Class
 import Control.Monad
+import Control.Monad.Trans.Class
+import Control.Monad.IO.Class
 import Control.Applicative
-import Data.Monoid
 import Data.Functor.Identity
-
--- | A discrete step in a continuous function. This type discretely describes 
--- an eventual value on the right and an output value on the left.
-data Step b c = Step { stepOutput :: b
-                     , stepResult :: Event c
-                     }
-
--- | Map the output value of a 'Step'.
-mapStepOutput :: (a -> b) -> Step a c -> Step b c
-mapStepOutput 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 a) where
-    fmap f (Step a b) = Step a $ fmap f b
-
--- | A discrete spline is a monoid if its left and right types are monoids.
-instance (Monoid f, Monoid b) => Monoid (Step f b) where
-    mempty = Step mempty (Event mempty)
-    mappend (Step a ea) (Step b eb) = Step (mappend a b) (mappend <$> ea <*> eb)
-
--- | A discrete spline is an applicative if its left datatype is a monoid. It
--- replies to 'pure' with an empty left value while the right value is the
--- argument wrapped in an event. It means "the argument happens instantly".
-instance Monoid f => Applicative (Step f) where
-    pure a = Step mempty $ Event a
-    (Step uia f) <*> (Step uib b) = Step (mappend uia uib) (f <*> b)
+import Data.Monoid
 
--- | 'SplineT' shares a number of types with 'VarT', specifically its monad,
--- input and output types (@m@, @a@ and @b@, respectively). A spline adds
--- a result type which represents the monadic computation's result
--- value.
+-- | 'SplineT' shares all the types of 'VarT' and adds a result value. Its
+-- monad, input and output types (@m@, @a@ and @b@, respectively) reflect the
+-- underlying 'VarT`. A spline adds a result type which represents the monadic
+-- computation's result value.
 -- Much like the State monad it has an "internal state" and an eventual
 -- result value, where the internal state is the output value. The result
 -- value is used only in determining the next spline to sequence.
-data SplineT a b m c = SplineT { unSplineT :: VarT m a (Step (Event b) c) }
-                     | SplineTConst c
-
--- | Unwrap a spline into a value stream.
-runSplineT :: (Applicative m, Monad m)
-           => SplineT a b m c -> VarT m a (Step (Event b) c)
-runSplineT (SplineT v) = v
-runSplineT (SplineTConst x) = pure $ pure x
-
--- | Run the spline over the input values, gathering the output and result 
--- values in a list. 
-scanSpline :: (Applicative m, Monad m) 
-           => SplineT a b m c -> [a] -> m [(Event b, Event c)]
-scanSpline s as = map f <$> scanVar (runSplineT s) as 
-    where f (Step eb ec) = (eb,ec)
+data SplineT a b m c where
+  Pass :: c -> SplineT a b m c
+  SplineT :: VarT m a (b, Event c) -> SplineT a b m c
 
--- | A SplineT monad parameterized with Identity that takes input of type @a@, 
--- output of type @b@ and a result value of type @c@.   
-type Spline a b c = SplineT a b Identity c
+-- | Convert a spline into a stream of output value and eventual result value
+-- tuples. Requires a default output value in case none are produced.
+runSplineT :: Monad m => SplineT a b m c -> b -> VarT m a (b, Event c)
+runSplineT (Pass c) b = pure (b, Event c)
+runSplineT (SplineT v) _ = VarT $ \a -> do
+  (o@(b,ec), v1) <- runVarT v a
+  let s = case ec of
+              NoEvent -> SplineT v1
+              Event c -> Pass c
+  return (o, runSplineT s b)
 
 -- | A spline is a functor by applying the function to the result.
-instance (Applicative m, Monad m) => Functor (SplineT a b m) where
-    fmap f (SplineTConst c)  = SplineTConst $ f c
-    fmap f (SplineT v) = SplineT $ fmap (fmap f) v
+instance Monad m => Functor (SplineT a b m) where
+  fmap f (Pass c) = Pass $ f c
+  fmap f (SplineT v) = SplineT (((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
--- argument. It responds to '<*>' by applying the left arguments eventual
--- value (the function) to the right arguments eventual value. The
--- output values will me combined with 'mappend'.
-instance (Applicative m, Monad m) => Applicative (SplineT a b m) where
-    pure = SplineTConst
-    (SplineTConst f) <*> (SplineTConst x) = SplineTConst $ f x
-    (SplineT vf) <*> (SplineTConst x) = SplineT $ fmap (fmap ($ x)) vf
-    (SplineTConst f) <*> (SplineT vx) = SplineT $ fmap (fmap f) vx
-    (SplineT vf) <*> (SplineT vx) = SplineT $ ((<*>) <$> vf) <*> vx
+-- A spline responds to 'pure' by returning a spline that never produces an
+-- output value and immediately returns the argument. It responds to '<*>' by
+-- applying the left arguments result value (the function) to the right
+-- arguments result value (the argument), sequencing them both in serial.
+instance Monad m => Applicative (SplineT a b m) where
+  pure = Pass
+  (Pass f) <*> (Pass x) = Pass $ f x
+  (Pass f) <*> (SplineT v) = f <$> SplineT v
+  (SplineT vf) <*> (Pass x) = ($ x) <$> SplineT vf
+  sf <*> sx = do
+    f <- sf
+    x <- sx
+    return $ f x
 
--- | 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 (Applicative m, Monad m) => Monad (SplineT a b m) where
-    return = pure
-    (SplineTConst x) >>= f = f x
-    (SplineT v) >>= f = SplineT $ VarT $ \i -> do
-        (Step b e, v') <- runVarT v i
-        case e of
-            NoEvent -> return (Step b NoEvent, runSplineT $ SplineT v' >>= f)
-            Event x -> runVarT (runSplineT $ f x) i
+-- | A spline responds to bind by running until it produces an eventual value,
+-- then uses that value to run the next spline.
+instance Monad m => Monad (SplineT a b m) where
+  return = Pass
+  (Pass x) >>= f = f x
+  (SplineT v) >>= f = SplineT $ VarT $ \a -> do
+    ((b, ec), v1) <- runVarT v a
+    case ec of
+      NoEvent -> return ((b, NoEvent), runSplineT (SplineT v1 >>= f) b)
+      Event c -> runVarT (runSplineT (f c) b) a
 
--- | A spline is a transformer and other monadic computations can be lifted
--- int a spline.
-instance MonadTrans (SplineT a b) where
-    lift f = SplineT $ varM $ const $ liftM (Step mempty . Event) f
+-- | A spline is a transformer if its output type is a Monoid.
+instance Monoid b => MonadTrans (SplineT a b) where
+  lift = effect mempty
 
 -- | 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 (Functor m, Applicative m, MonadIO m) => MonadIO (SplineT a b m) where
-    liftIO = lift . liftIO
+-- takes the result of the IO action as its immediate return value.
+instance (Monoid b, Monad m, MonadIO m) => MonadIO (SplineT a b m) where
+  liftIO = lift . liftIO
 
+-- | Run the spline over the input values, gathering the output and result
+-- values in a list.
+scanSpline :: (Applicative m, Monad m)
+           => SplineT a b m c -> b -> [a] -> m [b]
+scanSpline s b = scanVar (outputStream s b)
+
+-- | A SplineT monad parameterized with Identity that takes input of type @a@,
+-- output of type @b@ and a result value of type @c@.
+type Spline a b c = SplineT a b Identity c
+
 -- | Evaluates a spline into a value stream of its output type.
-outputStream :: (Applicative m, Monad m) 
-             => b -> SplineT a b m c -> VarT m a b
-outputStream x s = ((stepOutput <$>) $ runSplineT s) ~> foldStream (\_ y -> y) x
+outputStream :: (Applicative m, Monad m)
+             => SplineT a b m c -> b -> VarT m a b
+outputStream s b = fst <$> runSplineT s b
 
--- | Evaluates a spline to an event stream of its result. The resulting
--- value stream inhibits until the spline's domain is complete and then it
--- produces events of the result type.
-resultStream :: (Applicative m, Monad m) => SplineT a b m c -> VarT m a (Event c)
-resultStream = (stepResult <$>) . runSplineT
+resultStream :: (Applicative m, Monad m)
+             => SplineT a b m c -> b -> VarT m a (Event c)
+resultStream s b = snd <$> runSplineT s b
 
--- | Create a spline using an event stream. The spline will run until the
--- stream inhibits, using the stream's last produced value as the current
--- output value. In the case the stream inhibits before producing
--- a value the default value is used. The spline's result is the last
--- output value.
-fromEvents :: (Applicative m, Monad m) => b -> VarT m a (Event b) -> SplineT a b m b
-fromEvents x ve = SplineT $ VarT $ \a -> do
-    (ex, ve') <- runVarT 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 $ fromEvents x' ve'
-                           )
+-- | Create a spline from an event stream.
+fromEvent :: Monad m => VarT m a (Event b) -> SplineT a (Event b) m b
+fromEvent ve = SplineT $ f <$> ve
+  where f e = (e,e)
 
 -- | 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
@@ -179,88 +146,121 @@
 untilEvent :: (Applicative m, Monad m)
            => VarT m a b -> VarT m a (Event c)
            -> SplineT 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))
+untilEvent v ve = SplineT $ f <$> v <*> ve
+  where f b ec = (b, (b,) <$> ec)
 
 -- | A variant of 'untilEvent' that only results in the left result,
 -- discarding the right result.
 untilEvent_ :: (Applicative m, Monad m)
             => VarT m a b -> VarT m a (Event c)
             -> SplineT a b m b
-untilEvent_ v ve = fst <$> untilEvent v ve
+untilEvent_ v ve = SplineT $ f <$> v <*> ve
+  where f b ec = (b, b <$ ec)
 
 -- | A variant of 'untilEvent' that only results in the right result,
 -- discarding the left result.
 _untilEvent :: (Applicative m, Monad m)
             => VarT m a b -> VarT m a (Event c)
-            -> SplineT a b m b
-_untilEvent v ve = fst <$> untilEvent v ve
+            -> SplineT a b m c
+_untilEvent v ve = snd <$> untilEvent v ve
 
--- | Run two splines in parallel, combining their output. Return the result of 
--- the spline that concludes first. If they conclude at the same time the result 
+-- | A variant of 'untilEvent' that discards both the right and left results.
+_untilEvent_ :: (Applicative m, Monad m)
+             => VarT m a b -> VarT m a (Event c)
+             -> SplineT a b m ()
+_untilEvent_ v ve = void $ _untilEvent v ve
+
+-- | Run two splines in parallel, combining their output. Return the result of
+-- the spline that concludes first. If they conclude at the same time the result
 -- is taken from the left spline.
-race :: (Applicative m, Monad m) 
-     => (b -> d -> e) -> SplineT a b m c -> SplineT a d m c -> SplineT a e m c
-race f (SplineTConst a) s =
-    race f (SplineT $ pure $ Step mempty $ Event a) s
-race f s (SplineTConst b) =
-    race f s (SplineT $ pure $ Step mempty $ Event b)
+race :: (Applicative m, Monad m)
+     => (a -> b -> c) -> SplineT i a m d -> SplineT i b m e
+     -> SplineT i c m (Either d e)
+race _ (Pass x) _ = Pass $ Left x
+race _ _ (Pass x) = Pass $ Right x
 race f (SplineT va) (SplineT vb) = SplineT $ VarT $ \i -> do
-    (Step ua ea, va') <- runVarT va i
-    (Step ub eb, vb') <- runVarT vb i
-    let s' = runSplineT $ race f (SplineT va') (SplineT vb')
-    case (ea,eb) of
-        (Event a,_) -> return (Step (f <$> ua <*> ub) ea, s') 
-        (_,Event b) -> return (Step (f <$> ua <*> ub) eb, s') 
-        (_,_)       -> return (Step (f <$> ua <*> ub) NoEvent, s')
+    ((a, ed), va1) <- runVarT va i
+    ((b, ee), vb1) <- runVarT vb i
+    let c = f a b
+    case (ed,ee) of
+        (Event d,_) -> return ( (c, Event $ Left d), pure (c, Event $ Left d))
+        (_,Event e) -> return ( (c, Event $ Right e), pure (c, Event $ Right e))
+        (_,_)       -> return ( (c, NoEvent)
+                         , runSplineT (race f (SplineT va1) (SplineT vb1)) c
+                         )
 
--- | Run two splines in parallel, combining their output.  When both conclude, 
--- return their result values in a tuple.
-pair :: (Monad m) 
-     => (b -> d -> f) -> SplineT a b m c -> SplineT a d m e 
-     -> SplineT a f m (c, e)
-pair f (SplineTConst a) s = pair f (SplineT $ pure $ Step mempty $ Event a) s
-pair f s (SplineTConst b) = pair f s (SplineT $ pure $ Step mempty $ Event b)
-pair f (SplineT va) (SplineT vb) = SplineT $ VarT $ \a -> do
-    (Step fa ea, va') <- runVarT va a
-    (Step fb eb, vb') <- runVarT vb a
-    return ( Step (f <$> fa <*> fb) ((,) <$> ea <*> eb)
-           , runSplineT $ pair f (SplineT va') (SplineT vb')
-           )
+raceMany :: (Applicative m, Monad m, Monoid b)
+         => [SplineT a b m c] -> SplineT a b m c
+raceMany [] = pure mempty `_untilEvent` never
+--raceMany (Pass c:_) = Pass c
+raceMany ss = SplineT $ VarT $ \a -> do
+  let f (b, ec, ss1) s = do
+        ((b1, ec1), v1) <- runVarT (runSplineT s b) a
+        return (b <> b1, msum [ec, ec1], ss1 ++ [SplineT v1])
+  (b,ec,ss1) <- foldM f (mempty, NoEvent, []) ss
+  return ((b,ec), runSplineT (raceMany ss1) b)
 
+-- | Run two splines in parallel, combining their output. Once both splines
+-- have concluded, return the results of each in a tuple.
+merge :: (Applicative m, Monad m)
+     => (b -> b -> b) -> (c -> d -> e)
+     -> SplineT a b m c -> SplineT a b m d -> SplineT a b m e
+merge _ g (Pass c) (Pass d) = Pass $ g c d
+merge _ g (Pass c) s = g c <$> s
+merge _ g s (Pass d) = flip g d <$> s
+merge f g (SplineT v1) (SplineT v2) = SplineT $ VarT $ \a -> do
+  ((b1,e1), v3) <- runVarT v1 a
+  ((b2,e2), v4) <- runVarT v2 a
+  let b = f b1 b2
+  case (e1,e2) of
+    (Event c, Event d) -> let e = (b, Event $ g c d) in return (e, pure e)
+    (Event _, _) -> do let s = SplineT $ pure (b1,e1)
+                           sv4 = SplineT v4
+                       return ((b, NoEvent), runSplineT (merge f g s sv4) b)
+    (_, Event _) -> do let s = SplineT $ pure (b2,e2)
+                           sv3 = SplineT v3
+                       return ((b, NoEvent), runSplineT (merge f g sv3 s) b)
+    _ -> do let sv3 = SplineT v3
+                sv4 = SplineT v4
+            return ((b, NoEvent), runSplineT (merge f g sv3 sv4) b)
+
+-- | Run the side effect and use its result as the spline's result. This
+-- discards the output argument and switches immediately, but the argument is
+-- needed to construct the spline. For this reason spline's can't be an instance
+-- of MonadTrans or MonadIO.
+effect :: (Applicative m, Monad m) => b -> m x -> SplineT a b m x
+effect b f = SplineT $ VarT $ const $ do
+  x <- f
+  return ((b, Event x), pure (b, Event x))
+
 -- | Capture the spline's last output value and tuple it with the
 -- spline's result. 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, Eq b)
+capture :: (Applicative m, Monad m)
         => SplineT a b m c -> SplineT a b m (Maybe b, c)
-capture (SplineTConst x) = SplineTConst (Nothing, x)
-capture (SplineT v) = capture' Nothing v
-    where capture' mb v' = SplineT $ VarT $ \a -> do
-              (Step fb ec, v'') <- runVarT v' a
-              let mb' = if fb == NoEvent then mb else toMaybe fb
-                  ec' = (mb',) <$> ec
-              return (Step fb ec', runSplineT $ capture' mb' v'')
+capture (Pass x) = Pass (Nothing, x)
+capture (SplineT v) = capture' v
+    where capture' v' = SplineT $ VarT $ \a -> do
+              ((b, ec), v'') <- runVarT v' a
+              let mb' = Just b
+              return ((b, (mb',) <$> ec), runSplineT (capture' v'') b)
 
 -- | Produce the argument as an output value exactly once.
 step :: (Applicative m, Monad m) => b -> SplineT a b m ()
-step b = SplineT $ VarT $ \_ ->
-    return (Step (pure b) NoEvent, pure $ Step (pure b) $ Event ())
+step b = SplineT $ VarT $ \_ -> return ((b, NoEvent), pure (b,Event ()))
 
 -- | Map the output value of a spline.
-mapOutput :: (Applicative m, Monad m) 
+mapOutput :: (Applicative m, Monad m)
           => VarT m a (b -> t) -> SplineT a b m c -> SplineT a t m c
-mapOutput _ (SplineTConst c) = SplineTConst c
-mapOutput vf (SplineT vx) = SplineT $ mapStepOutput <$> vg <*> vx
-    where vg = (<$>) <$> vf
+mapOutput vf (SplineT vx) = SplineT $ vg <*> vx
+    where vg = (\f (b,ec) -> (f b, ec)) <$> vf
+mapOutput _ (Pass c) = Pass c
 
 -- | Map the input value of a spline.
 adjustInput :: (Monad m)
             => VarT m a (a -> r) -> SplineT r b m c -> SplineT a b m c
-adjustInput _ (SplineTConst c) = SplineTConst c
 adjustInput vf (SplineT vx) = SplineT $ VarT $ \a -> do
-    (f, vf') <- runVarT vf a
-    (b, vx') <- runVarT vx $ f a
-    return (b, runSplineT $ adjustInput vf' $ SplineT vx')
+    (f, vf1) <- runVarT vf a
+    (b, vx1) <- runVarT vx $ f a
+    return (b, runSplineT (adjustInput vf1 $ SplineT vx1) $ fst b)
+adjustInput _ (Pass c) = Pass c
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
@@ -2,47 +2,22 @@
 --   Copyright:  (c) 2015 Schell Scivally
 --   License:    MIT
 --   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>
-{-# LANGUAGE TupleSections #-}
 module Control.Varying.Time where
 
 import Control.Varying.Core
 import Control.Varying.Event
 import Control.Applicative
-import Data.Time.Clock
-import Control.Monad.IO.Class (MonadIO,liftIO)
-
--- | Produces time deltas using 'getCurrentTime' and 'diffUTCTime'.
-deltaUTC :: (MonadIO m, Fractional t) => VarT m b t
-deltaUTC = delta (liftIO getCurrentTime) (\a b -> realToFrac $ diffUTCTime a b)
-
--- | 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) -> VarT m b t
-delta m f = VarT $ \_ -> do
-    t <- m
-    return (0, delta' t)
-    where delta' t = VarT $ \_ -> do
-            t' <- m
-            let dt = t' `f` t
-            return (dt, delta' t')
 --------------------------------------------------------------------------------
 -- Using timed events
 --------------------------------------------------------------------------------
 -- | 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 :: (Applicative m, Monad m, Num t, Ord t) => t -> VarT m t (Event ())
-before t = VarT $ \dt -> return $
-    if t - dt >= 0
-    then (Event (), before $ t - dt)
-    else (NoEvent, never)
+-- and therefore an event will be never be emitted exactly at time == t.
+before :: (Applicative m, Monad m, Num t, Ord t) => t -> VarT m t (Event t)
+before t = accumulate (+) 0 ~> onWhen (< t)
 
 -- | 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 -> VarT m t (Event ())
-after t = VarT $ \dt -> return $
-    if t - dt <= 0
-    then (Event (), pure $ Event ())
-    else (NoEvent, after $ t - dt)
+-- since it depends on the input.
+after :: (Applicative m, Monad m, Num t, Ord t) => t -> VarT m t (Event t)
+after t = accumulate (+) 0 ~> onWhen (>= t)
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
@@ -137,7 +137,7 @@
 -- resulting spline will take a time delta as input. For example:
 --
 -- @
--- testWhile_ isEvent (deltaUTC ~> v)
+-- testWhile_ isEvent (deltaUTC >>> v)
 --    where v :: VarT IO a (Event Double)
 --          v = execSpline 0 $ tween easeOutExpo 0 100 5
 -- @
@@ -147,16 +147,20 @@
 -- more than once ;)
 tween :: (Applicative m, Monad m, Fractional t, Ord t)
       => Easing t -> t -> t -> t -> SplineT t t m t
-tween f start end dur = fromEvents 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 NoEvent else Event x
+tween f start end dur =
+  let c = end - start
+      b = start
+      vt = h <$> timeAsPercentageOf dur
+      h t = if t >= 1.0
+            then (end, Event end)
+            else (f c t b, NoEvent)
+  in SplineT vt
 
+
 -- | Creates a tween that performs no interpolation over the duration.
 constant :: (Applicative m, Monad m, Num t, Ord t)
          => a -> t -> SplineT t a m a
-constant value duration = fromEvents value $ use value $ before duration
+constant value duration = pure value `untilEvent_` after duration
 
 -- | VarTies 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)
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,107 +1,214 @@
 module Main where
 
-import Test.Hspec hiding (after)
+import Test.Hspec hiding (after, before)
 import Test.QuickCheck
 import Control.Varying
 import Data.Functor.Identity
+import Data.Time.Clock
+import Control.Monad.IO.Class
 
 main :: IO ()
-main = hspec $ do 
-    describe "timeAsPercentageOf" $ do
-        it "should run past 1.0" $ do
-            let Identity scans = scanVar (timeAsPercentageOf 4)
-                                         [1,1,1,1,1 :: Float]
-            last scans `shouldSatisfy` (> 1)
-        it "should progress by increments of the total" $ do
-            let Identity scans = scanVar (timeAsPercentageOf 4)
-                                         [1,1,1,1,1 :: Float]
-            scans `shouldBe` [0.25,0.5,0.75,1.0,1.25 :: Float] 
+main = hspec $ do
+  describe "before" $ do
+    it "should produce events before a given step" $ do
+      let Identity scans = scanVar (1 ~> before 3) $ replicate 4 ()
+      scans `shouldBe` [Event 1, Event 2, NoEvent, NoEvent]
 
-    describe "tween" $ 
-        it "should step by the dt passed in" $ do
-            let Identity scans = scanSpline (tween linear 0 4 (4 :: Float)) 
-                                            [0,1,1,1,1,1] 
-            scans `shouldBe` [(Event 0, NoEvent)
-                             ,(Event 1, NoEvent)
-                             ,(Event 2, NoEvent)
-                             ,(Event 3, NoEvent)
-                             ,(Event 4, NoEvent)
-                             ,(Event 4, Event 4)
-                             ]
+  describe "after" $ do
+    it "should produce events after a given step" $ do
+      let Identity scans = scanVar (1 ~> after 3) $ replicate 4 ()
+      scans `shouldBe` [NoEvent, NoEvent, Event 3, Event 4]
+  describe "anyE" $ do
+    it "should produce on any event" $ do
+      let v1 = use 1 (1 ~> before 2)
+          v2 = use 2 (1 ~> after 3)
+          v3 = always 3
+          v = anyE [v1,v2,v3]
+          Identity scans = scanVar v $ replicate 4 ()
+      scans `shouldBe` [Event 1, Event 3, Event 2, Event 2]
+  describe "timeAsPercentageOf" $ do
+      it "should run past 1.0" $ do
+          let Identity scans = scanVar (timeAsPercentageOf 4)
+                                       [1,1,1,1,1 :: Float]
+          last scans `shouldSatisfy` (> 1)
+      it "should progress by increments of the total" $ do
+          let Identity scans = scanVar (timeAsPercentageOf 4)
+                                       [1,1,1,1,1 :: Float]
+          scans `shouldBe` [0.25,0.5,0.75,1.0,1.25 :: Float]
 
-    describe "untilEvent" $ do
-        let Identity scans = scanSpline (3 `untilEvent` (1 ~> after 10))
-                                        (replicate 10 ())
-        it "should produce output from the value stream until event procs" $
-            head scans `shouldBe` (Event 3, NoEvent)
-        it "should produce output from the value stream until event procs" $
-            last scans `shouldBe` (Event 3, Event (3,()))
+  describe "tween" $
+      it "should step by the dt passed in" $ do
+          let Identity scans = scanSpline (tween linear 0 4 (4 :: Float)) 0
+                                          [0,1,1,1,1,1]
+          scans `shouldBe` [0,1,2,3,4,4]
 
-    describe "pair" $ do
-        let s1 = 3 `untilEvent_` (1 ~> after 10)
-            s2 = do 4 `untilEvent_` (1 ~> after 10)
-                    5 `untilEvent_` (1 ~> after 10)
-            Identity scans = scanSpline (pair (+) s1 s2) $ replicate 20 () 
-        it "should end" $
-            length (takeWhile ((== NoEvent) . snd) scans) `shouldBe` 18 
-        it "should combine output" $
-            head scans `shouldBe` (Event 7, NoEvent)
-        it "should progress" $
-            (scans !! 11) `shouldBe` (Event 8, NoEvent)
-        it "should pair both results" $
-            last scans `shouldBe` (Event 8, Event (3,5))
+  describe "untilEvent" $ do
+      let Identity scans = scanSpline (3 `untilEvent` (1 ~> after 10)) 0
+                                      (replicate 10 ())
+      it "should produce output from the value stream until event procs" $
+          head scans `shouldBe` 3
+      it "should produce output from the value stream until event procs" $
+          last scans `shouldBe` 3
 
-    describe "race" $ do
-        let s1 = pure 'a' `untilEvent_` (1 ~> after 3)
-            s2 = pure 'x' `untilEvent_` (1 ~> after 4)
-            r  = race (\a x -> [a,x]) s1 s2
-            Identity scans = scanSpline r $ replicate 20 ()
-        it "should combine output" $
-            head scans `shouldBe` (Event "ax", NoEvent) 
-        it "should end" $
-            length (takeWhile ((== NoEvent) . snd) scans) `shouldBe` 2
-        it "should show 'a' as winner" $
-            last scans `shouldBe` (Event "ax", Event 'a')
+  describe "step" $ do
+      let s = do step "hey"
+                 step ", "
+                 step "there"
+                 step "."
+          Identity scans = scanSpline s "" $ replicate 6 ()
+      it "should produce output exactly one time per call" $
+        concat scans `shouldBe` "hey, there..."
 
-    describe "capture" $ do
-        let fstr str char = str ++ [char]
-            s = (1 ~> accumulate (+) (fromEnum 'a') 
-                   ~> var toEnum 
-                   ~> accumulate fstr "") 
-                   `untilEvent_` (1 ~> after 3)
-            Identity scans = scanSpline (capture s) $ replicate 5 ()
-        it "should end with the last value captured" $ 
-            scans !! 2 `shouldBe` (Event "bcd", Event (Just "bcd", "bcd")) 
-    
-    describe "step" $ do
-        let s = step "hey"
-            Identity scans = scanSpline s $ replicate 3 ()
-        it "should produce exactly once" $ do
-            head scans `shouldBe` (Event "hey", NoEvent)
-            scans !! 1 `shouldBe` (Event "hey", Event ())
+  describe "fromEvent" $ do
+    let s = fromEvent $ var f ~> onJust
+        f 0 = Nothing
+        f 1 = Just "YES"
+        Identity scans = scanSpline s NoEvent [0,0,0,1,0]
+    it "should produce NoEvent until it procs" $
+      scans `shouldBe` [NoEvent,NoEvent,NoEvent,Event "YES",Event "YES"]
 
-    describe "mapOutput" $ do
-        let s :: Spline () String String 
-            s = pure "hey" `untilEvent_` never
-            f :: Int -> Char -> Int
-            f acc char = acc + fromEnum char
-            g :: String -> Int
-            g = foldl f 0
-            v :: Var () (String -> Int)
-            v = var $ const g 
-            s' = mapOutput v s 
-            Identity scans = scanSpline s' $ replicate 3 ()
-        it "should map the output" $ 
-            head scans `shouldBe` (Event 326, NoEvent) 
+  describe "effect" $ do
+    let s :: SplineT () String IO ()
+        s = do step "Getting the time..."
+               utc <- effect "running" $ getCurrentTime
+               let t = head $ words $ show utc
+               step t
+               step "The End"
+    it "should step once, get the time and then step with a string of the time"
+       $ do utc <- getCurrentTime
+            let t = head $ words $ show utc
+            scans <- liftIO $ scanSpline s "" [(), (), ()]
+            scans `shouldBe` ["Getting the time...", t, "The End"]
+  describe "race" $ do
+      let s1 = do step "s10"
+                  step "s11"
+                  step "s12"
+                  return (1 :: Int)
+          s2 = do step "s20"
+                  step "s21"
+                  return True
+          r = do step "start"
+                 eIntBool <- race (\a b -> concat [a,":",b]) s1 s2
+                 case eIntBool of
+                   Left i -> step $ "left won with " ++ show i
+                   Right b -> step $ "right won with " ++ show b
+          Identity scans = scanSpline r "" $ replicate 4 ()
+      it "should step twice and left should win" $
+        unwords scans `shouldBe` "start s10:s20 s11:s21 right won with True"
 
-    describe "adjustInput" $ do
-        let s = var id `untilEvent_` never
-            v :: Var a (Char -> Int) 
-            v = pure fromEnum 
-            s' = adjustInput v s
-            Identity scans = scanSpline s' "abcd"
-        it "should" $ map fst scans `shouldBe` [ Event 97
-                                               , Event 98
-                                               , Event 99
-                                               , Event 100
-                                               ]
+  describe "raceMany" $ do
+    let s1 = do step "t"
+                step "c"
+                return 0
+        s2 = do step "h"
+                step "a"
+                return 1
+        s3 = do step "e"
+                step "t"
+                return (2 :: Int)
+        s = do x <- raceMany [s1,s2,s3]
+               step $ show x
+        Identity scans = scanSpline s "" $ replicate 3 ()
+    it "should output in parallel (mappend) and return the first or leftmost result" $ unwords scans `shouldBe` "the cat 0"
+
+  describe "capture" $ do
+      let r :: Spline () String ()
+          r = do x <- capture $ do step "a"
+                                   step "b"
+                                   return 2
+                 case x of
+                   (Just "b", 2) -> step "True"
+                   _ -> step "False"
+          scans = scanSpline r "" $ replicate 3 ()
+      it "should end with the last value captured" $
+          unwords (concat scans) `shouldBe` "a b True"
+
+  describe "mapOutput" $ do
+      let s :: Spline a Char ()
+          s = do step 'a'
+                 step 'b'
+                 step 'c'
+                 let f = pure toEnum
+                 mapOutput f $ do step 100
+                                  step 101
+                                  step 102
+                 step 'g'
+          Identity scans = scanSpline s 'x' $ replicate 7 ()
+      it "should map the output" $
+          scans `shouldBe` "abcdefg"
+
+  describe "adjustInput" $ do
+      let s = var id `untilEvent_` never
+          v :: Var a (Char -> Int)
+          v = pure fromEnum
+          s' = adjustInput v s
+          Identity scans = scanSpline s' 0 "abcd"
+      it "should" $ scans `shouldBe` [97,98,99,100]
+--------------------------------------------------------------------------------
+-- Adherance to typeclass laws
+--------------------------------------------------------------------------------
+  let inc = 1 ~> accumulate (+) 0
+      sinc :: Spline a Int (Int, Int)
+      sinc = inc `untilEvent` (1 ~> after 3)
+      go a = scanSpline a 0 [0..9]
+      equal a b = go a `shouldBe` go b
+
+  describe "spline's functor instance" $ do
+    let sincf = fmap id sinc
+    it "fmap id = id" $ equal sinc sincf
+    let g :: (Int, Int) -> (Int, Int)
+        g (x,y) = (x + 1, y)
+        f (x,y) = (x - 1, y)
+        sdot = fmap (g . f) sinc
+        sfdot = fmap g $ fmap f sinc
+    it "fmap (g . f) = fmap g . fmap f" $ equal sdot sfdot
+
+  describe "spline's applicative instance" $ do
+    let ident = pure id <*> sinc
+    it "(identity) pure id <*> v = v" $ equal ident sinc
+    let pfpx :: Spline a Int Int
+        pfpx = pure (+1) <*> pure 1
+        pfx = pure (1+1)
+    it "(homomorphism) pure f <*> pure x = pure (f x)" $ equal pfpx pfx
+    let u :: Spline a Int (Int -> Int)
+        u = pure 66 `_untilEvent` (use (+1) $ 1 ~> after 3)
+        upy = u <*> pure 1
+        pyu = pure ($ 1) <*> u
+    it "(interchange) u <*> pure y = pure ($ y) <*> u" $ equal upy pyu
+    let v :: Spline a Int (Int -> Int)
+        v = pure 66 `_untilEvent` (use (1-) $ 1 ~> after 4)
+        w = pure 72 `_untilEvent` (use 3 $ 1 ~> after 1)
+        pduvw = pure (.) <*> u <*> v <*> w
+        uvw = u <*> (v <*> w)
+    it "(compisition) pure (.) <*> u <*> v <*> w = u <*> (v <*> w)" $
+      equal pduvw uvw
+
+  describe "spline's monad instance" $ do
+    let h = sinc
+        hr = h >>= return
+        p :: Spline a Int Int
+        p = pure 1
+
+    it "(right identity w/ const) m >>= return == m" $ equal (p >>= return) p
+    it "(right identity) m >>= return == m" $ equal h hr
+    it "(right identity w/ monadic results) m >>= return == m" $
+      (scanVar (runSplineT h 0) [0..9])
+        `shouldBe` scanVar (runSplineT hr 0) [0..9]
+    let f :: Int -> Spline a String Bool
+        f x = do mapM_ (step . show) [0..x]
+                 return True
+    it "(left identity) return a >>= f == f a" $
+      (scanVar (runSplineT (return 3 >>= f) "") [0..9])
+        `shouldBe` scanVar (runSplineT (f 3) "") [0..9]
+    let m :: Spline a String Int
+        m = do step "hey"
+               step "dude"
+               return 2
+        g :: Bool -> Spline a String ()
+        g True = do step "okay"
+                    step "got it"
+        g False = do step "dang"
+                     step "missed it"
+    it "(associativity) (m >>= f) >>= g == m >>= (\\x -> f x >>= g)" $
+      (scanVar (runSplineT ((m >>= f) >>= g) "") [0..9])
+        `shouldBe` scanVar (runSplineT (m >>= (\x -> f x >>= g)) "") [0..9]
diff --git a/varying.cabal b/varying.cabal
--- a/varying.cabal
+++ b/varying.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.4.0.0
+version:             0.5.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            FRP through value streams and monadic splines.
@@ -118,6 +118,26 @@
 
   -- Directories containing source files.
   hs-source-dirs:      test
+
+  main-is:             Main.hs
+
+  -- Base language which the package is written in.
+  default-language:    Haskell2010
+
+benchmark varying-bench
+  type:                exitcode-stdio-1.0
+  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
+
+  -- Other library packages from which modules are imported.
+  build-depends:       base >=4.7 && <4.9
+                     , time >=1.5 && <1.6
+                     , transformers
+                     , varying
+                     , criterion
+
+
+  -- Directories containing source files.
+  hs-source-dirs:      bench
 
   main-is:             Main.hs
 
