diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@
 -- An exponential tween back and forth from 0 to 50 over 1 seconds that
 -- loops forever. This spline takes float values of delta time as input,
 -- outputs the current x value at every step.
-tweenx :: (Applicative m, Monad m) => TweenT Float Float m Float
+tweenx :: Monad m => TweenT Float Float m Float
 tweenx = do
     -- Tween from 0 to 50 over 1 second
     tween_ easeOutExpo 0 50 1
@@ -35,20 +35,20 @@
     -- Loop forever
     tweenx
 
--- A quadratic tween back and forth from 0 to 50 over 1 seconds that never
+-- An exponential tween back and forth from 0 to 50 over 1 seconds that never
 -- ends.
-tweeny :: (Applicative m, Monad m) => TweenT Float Float m Float
+tweeny :: Monad m => TweenT Float Float m Float
 tweeny = do
     tween_ easeOutExpo 50 0 1
     tween_ easeOutExpo 0 50 1
     tweeny
 
 -- Our time signal counts input delta time samples.
-time :: (Applicative m, Monad m) => VarT m Delta Float
+time :: Monad m => VarT m Delta Float
 time = var unDelta
 
 -- | Our Point value that varies over time continuously in x and y.
-backAndForth :: (Applicative m, Monad m) => VarT m Delta 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
@@ -93,4 +93,17 @@
       f _ _ = ' '
   putStrLn str
   loop vNext t1
+```
+
+# Publications
+
+The concept of `VarT` that this library is built on is isomorphic to Monadic Stream Functions as defined in "[Functional Reactive Programming, Refactored](http://dl.acm.org/citation.cfm?id=2976010)" ([mirror](http://www.cs.nott.ac.uk/~psxip1/#FRPRefactored)).
+
+The isomorphism is
+``` haskell
+toMSF :: Functor m => VarT m a b -> MSF m a b
+toMSF = MSF . (fmap . fmap . fmap $ toMSF) . runVarT
+
+toVarT :: Functor m => MSF m a b -> VarT m a b
+toVarT = VarT . (fmap . fmap . fmap $ toVarT) . unMSF
 ```
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -1,39 +1,51 @@
 module Main where
 
-import Control.Varying
-import Control.Applicative
-import Control.Monad (void)
-import Data.Functor.Identity
-import Data.Function (fix)
-import Data.Time.Clock
+import           Control.Concurrent    (threadDelay)
+import           Control.Varying
+import           Data.Function         (fix)
+import           Data.Functor.Identity (Identity (..))
+import           Data.Time.Clock       (diffUTCTime, getCurrentTime)
 
 -- | A simple 2d point type.
 data Point = Point { px :: Float
                    , py :: Float
                    } deriving (Show, Eq)
 
+
+-- | The duration (in seconds) to tween in each direction.
+dur :: Float
+dur = 3
+
+
+-- | A novel, start-stop tween.
+easeMiddle :: Monad m => Float -> Float -> Float -> TweenT Float Float m ()
+easeMiddle start end t = do
+  let change = end - start
+  tween_ easeOutExpo start              (start + change/2) $ t/2
+  tween_ easeInExpo  (start + change/2) end                $ t/2
+
 -- An exponential tween back and forth from 0 to 50 over 1 seconds that
 -- loops forever. This spline takes float values of delta time as input,
 -- outputs the current x value at every step.
-tweenx :: (Applicative m, Monad m) => TweenT Float Float m Float
+tweenx :: Monad m => TweenT Float Float m ()
 tweenx = do
-    -- Tween from 0 to 50 over 1 second
-    tween_ easeOutExpo 0 50 1
+    -- Tween from 0 to 50 over 'dur' seconds
+    easeMiddle 0 50 dur
     -- Chain another tween back to the starting position
-    tween_ easeOutExpo 50 0 1
+    easeMiddle 50 0 dur
     -- Loop forever
     tweenx
 
 -- A quadratic tween back and forth from 0 to 50 over 1 seconds that never
 -- ends.
-tweeny :: (Applicative m, Monad m) => TweenT Float Float m Float
+tweeny :: Monad m => TweenT Float Float m ()
 tweeny = do
-    tween_ easeOutExpo 50 0 1
-    tween_ easeOutExpo 0 50 1
+    easeMiddle 50 0 dur
+    easeMiddle 0 50 dur
     tweeny
 
 -- | Our Point value that varies over time continuously in x and y.
-backAndForth :: (Applicative m, Monad m) => VarT m Float Point
+backAndForth :: Monad m => VarT m Float Point
 backAndForth =
     -- Turn our splines into continuous output streams. We must provide
     -- a starting value since splines are not guaranteed to be defined at
@@ -44,31 +56,23 @@
     -- Construct a varying Point that takes time as an input.
     (Point <$> x <*> y)
 
--- | An example of using 'fix' and combining splines to get a better programming
--- experience while writing tweens.
-betterBackAndForth :: (Applicative m, Monad m) => VarT m Float Point
-betterBackAndForth = flip tweenStream (Point 0 0) $ fix $ \nxt -> do
-  void $ race Point (tween_ easeOutExpo 0 50 1) (tween_ easeOutExpo 50 0 1)
-  void $ race Point (tween_ easeOutExpo 50 0 1) (tween_ easeOutExpo 0 50 1)
-  nxt
-
 main :: IO ()
-main = getCurrentTime >>= loop betterBackAndForth
-
-loop :: Var Float Point -> UTCTime -> IO ()
-loop v t = do
-  t1 <- getCurrentTime
-  -- Here we'll run in the Identity monad using a time delta provided by
-  -- getCurrentTime and diffUTCTime.
-  let dt = realToFrac $ diffUTCTime t1 t
-      Identity (Point x y, vNext) = runVarT v dt
-      xStr = replicate (round x) ' ' ++ "x" ++ replicate (50 - round x) ' '
-      yStr = replicate (round y) ' ' ++ "y" ++ replicate (50 - round y) ' '
-      str  = zipWith f xStr yStr
-      f 'x' 'y' = '|'
-      f 'y' 'x' = '|'
-      f a ' ' = a
-      f ' ' b = b
-      f _ _ = ' '
-  putStrLn str
-  loop vNext t1
+main = do
+  t <- getCurrentTime
+  ($ t) . ($ backAndForth) $ fix $ \loop v lastT -> do
+    thisT <- getCurrentTime
+    -- Here we'll run in the Identity monad using a time delta provided by
+    -- getCurrentTime and diffUTCTime.
+    let dt = realToFrac $ diffUTCTime thisT lastT
+        Identity (Point x y, vNext) = runVarT v dt
+        xStr = replicate (round x) ' ' ++ "x" ++ replicate (50 - round x) ' '
+        yStr = replicate (round y) ' ' ++ "y" ++ replicate (50 - round y) ' '
+        str  = zipWith f xStr yStr
+        f 'x' 'y' = '|'
+        f 'y' 'x' = '|'
+        f a ' '   = a
+        f ' ' b   = b
+        f _ _     = ' '
+    putStrLn str
+    threadDelay $ floor $ 1000000 / (20 :: Double)
+    loop vNext thisT
diff --git a/src/Control/Varying.hs b/src/Control/Varying.hs
--- a/src/Control/Varying.hs
+++ b/src/Control/Varying.hs
@@ -2,13 +2,13 @@
 --  Module:     Control.Varying
 --  Copyright:  (c) 2016 Schell Scivally
 --  License:    MIT
---  Maintainer: Schell Scivally <efsubenovex@gmail.com>
+--  Maintainer: Schell Scivally <schell@takt.com>
 --
 --  [@Core@]
---  Automaton based value streams. 
+--  Automaton based value streams.
 --
 --  [@Event@]
---  Discontinuous value streams that occur only sometimes. 
+--  Discontinuous value streams that occur only sometimes.
 --
 --  [@Spline@]
 --  Sequencing of value and event streams using do-notation to form complex
@@ -18,15 +18,12 @@
 --  Tween numerical values over time using common easing functions. Great for
 --  animation.
 --
-module Control.Varying
-  ( -- * Reexports
-    module Control.Varying.Core
-  , module Control.Varying.Event
-  , module Control.Varying.Spline
-  , module Control.Varying.Tween
-  ) where
+module Control.Varying (
+  -- * Reexports
+  module V
+) where
 
-import Control.Varying.Core
-import Control.Varying.Event
-import Control.Varying.Tween
-import Control.Varying.Spline 
+import           Control.Varying.Core   as V
+import           Control.Varying.Event  as V
+import           Control.Varying.Spline as V
+import           Control.Varying.Tween  as V
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,46 +1,44 @@
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE GADTs               #-}
+{-# LANGUAGE LambdaCase          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
-#if __GLASGOW_HASKELL__ > 710 
-{-# OPTIONS_GHC -Wno-redundant-constraints #-}
-#endif
 -- |
 --   Module:     Control.Varying.Core
 --   Copyright:  (c) 2015 Schell Scivally
 --   License:    MIT
---   Maintainer: Schell Scivally <efsubenovex@gmail.com>
+--   Maintainer: Schell Scivally <schell@takt.com>
 --
 --   Varying values represent values that change over a given domain.
 --
---   A stream/signal takes some input know as the domain (e.g. time, place, etc)
---   and when sampled using 'runVarT' - produces a value and a new 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.
+--   A varying value takes some input as its domain (e.g. time, place, etc)
+--   and when run using 'runVarT' it produces a value and a new varying value.
+--   This pattern is known as an automaton and `varying` uses this pattern at its
+--   core. With the additon of monadic event sequencing, 'varying' makes it easy
+--   to construct complicated signals that control program and data flow.
 module Control.Varying.Core
   ( -- * Types and Typeclasses
     Var
   , VarT(..)
-    -- * Creating streams
+    -- * Creating vars
     -- $creation
   , done
   , var
   , arr
   , varM
   , mkState
-    -- * Composing streams
+    -- * Composing vars
     -- $composition
   , (<<<)
   , (>>>)
     -- * Adjusting and accumulating
   , delay
   , accumulate
-    -- * Sampling streams (running and other entry points)
+    -- * Sampling vars (running and other entry points)
     -- $running
   , scanVar
   , stepMany
-    -- * Debugging and tracing streams in flight
+    -- * Debugging and tracing vars in flight
   , vtrace
   , vstrace
   , vftrace
@@ -49,52 +47,54 @@
     -- $proofs
   ) where
 
-import Prelude hiding (id, (.))
-import Control.Arrow
-import Control.Category
-import Control.Monad
-import Control.Monad.IO.Class
-import Data.Functor.Identity
-import Debug.Trace
-import Control.Applicative 
-#if __GLASGOW_HASKELL__ < 710
-import Data.Monoid
-#endif
+import           Control.Applicative
+import           Control.Arrow
+import           Control.Category
+import           Control.Monad
+import           Control.Monad.Fix
+import           Control.Monad.IO.Class
+import           Data.Functor.Contravariant
+import           Data.Functor.Identity
+import           Debug.Trace
+import           Prelude                    hiding (id, (.))
+
 --------------------------------------------------------------------------------
 -- Core datatypes
 --------------------------------------------------------------------------------
--- | A stream parameterized with Identity that takes input of type @a@
+-- | A continuously varying value, with effects.
+-- It's a kind of <https://en.wikipedia.org/wiki/Mealy_machine Mealy machine>
+-- (an automaton).
+newtype VarT m a b = VarT { runVarT :: a -> m (b, VarT m a b) }
+                            -- ^ Run a @VarT@ computation with an input value of
+                            -- type 'a', yielding a step - a value of type 'b'
+                            -- and a new computation for yielding the next step.
+
+
+-- | A var parameterized with Identity that takes input of type @a@
 -- and gives output of type @b@. This is the pure, effect-free version of
 -- 'VarT'.
 type Var a b = VarT Identity a b
 
--- | A stream is a structure that contains a value that changes over some
--- input. It's a kind of
--- <https://en.wikipedia.org/wiki/Mealy_machine Mealy machine> (an automaton)
--- with effects. Using 'runVarT' with an input value of type 'a' yields a
--- "step", which is a value of type 'b' and a new stream for yielding the next
--- value.
-newtype 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.
 --------------------------------------------------------------------------------
 -- Typeclass instances
 --------------------------------------------------------------------------------
--- | You can transform the output value of any stream:
+-- | You can transform the output value of any var:
 --
 -- >>> let v = 1 >>> fmap (*3) (accumulate (+) 0)
 -- >>> testVarOver v [(),(),()]
 -- 3
 -- 6
 -- 9
-instance (Applicative m, Monad m) => Functor (VarT m b) where
-  fmap f v = (var f) . v
--- | A very simple category instance. 
---
+instance Applicative m => Functor (VarT m b) where
+  fmap f v = VarT $ (g <$>) . runVarT v
+    where g (b, vb) = (f b, f <$> vb)
+
+-- | A var is a category.
 -- @
 --   id = var id
 --   f . g = g >>> f
 -- @
+--
 -- or
 --
 -- >  f . g = f <<< g
@@ -104,28 +104,27 @@
 -- 1
 -- 2
 -- 3
-instance (Applicative m, Monad m) => Category (VarT m) where
+instance Monad m => Category (VarT m) where
     id = var id
-    f0 . g0 = VarT $ \(!a) -> do
+    f0 . g0 = VarT $ \a -> do
       (b, g) <- runVarT g0 a
       (c, f) <- runVarT f0 b
       return (c, f . g)
 
--- | Streams are applicative.
+-- | Vars are applicative.
 --
 -- >>> let v = (,) <$> pure True <*> pure "Applicative"
 -- >>> testVarOver v [()]
 -- (True,"Applicative")
 --
 -- Note - checkout the <$proofs proofs>
-instance (Applicative m, Monad m) => Applicative (VarT m a) where
+instance Applicative m => Applicative (VarT m a) where
     pure = done
-    vf <*> vx = VarT $ \(!a) -> do
-      (f, vf') <- runVarT vf a
-      (x, vx') <- runVarT vx a
-      return (f x, vf' <*> vx')
+    vf <*> vx = VarT $ \a ->
+      g <$> runVarT vf a <*> runVarT vx a
+      where g (f, vf1) (x, vx1) = (f x, vf1 <*> vx1)
 
--- | Streams are arrows, which means you can use proc notation, among other
+-- | Vars are arrows, which means you can use proc notation, among other
 -- meanings.
 --
 -- >>> :set -XArrows
@@ -147,28 +146,76 @@
 -- 3
 -- 5
 -- 7
-instance (Applicative m, Monad m) => Arrow (VarT m) where
+instance Monad m => Arrow (VarT m) where
   arr = var
-  first v = VarT $ \(b,d) -> do (c, v') <- runVarT v b
-                                return ((c,d), first v')
+  first v = VarT $ \(b, d) -> g d <$> runVarT v b
+    where g d (c, v') = ((c, d), first v')
 
--- | Streams can be monoids
+instance MonadPlus m => ArrowZero (VarT m) where
+  zeroArrow = varM $ const mzero
+
+instance MonadPlus m => ArrowPlus (VarT m) where
+  VarT f <+> VarT g = VarT $ \a -> f a `mplus` g a
+
+-- |
+instance Monad m => ArrowChoice (VarT m) where
+  left f  = f +++ arr id
+  right f = arr id +++ f
+  f +++ g = (f >>> arr Left) ||| (g >>> arr Right)
+  f ||| g = VarT $ \case
+    Left b -> do
+      (d, f1) <- runVarT f b
+      return (d, f1 ||| g)
+    Right c -> do
+      (d, g1) <- runVarT g c
+      return (d, f ||| g1)
+
+instance Monad m => ArrowApply (VarT m) where
+  app = VarT $ \(v, b) -> do
+    (c, _) <- runVarT v b
+    return (c, app)
+
+instance MonadFix m => ArrowLoop (VarT m) where
+  loop vmbdcd = VarT $ \b -> fmap fst $ mfix $ \(_, d) -> do
+    ((c1, d1), vmbdcd1) <- runVarT vmbdcd (b, d)
+    return ((c1, loop vmbdcd1), d1)
+
+-- | VarT with its input and output parameters flipped.
+newtype FlipVarT m b a = FlipVarT { unFlipVarT :: VarT m a b }
+
+-- | A VarT is contravariant when the type arguments are flipped.
+instance Monad m => Contravariant (FlipVarT m b) where
+  contramap f (FlipVarT vmab) = FlipVarT $ VarT $ \c -> do
+    (b, vmab1) <- runVarT vmab $ f c
+    return (b, unFlipVarT $ contramap f $ FlipVarT vmab1)
+
+#if __GLASGOW_HASKELL__ >= 804
+-- | Vars can be semigroups
 --
+-- >>> let v = var (const "Hello ") <> var (const "World!")
+-- >>> testVarOver v [()]
+-- "Hello World!"
+instance (Applicative m, Semigroup b) => Semigroup (VarT m a b) where
+  (<>) = liftA2 (<>)
+#endif
+
+-- | Vars can be monoids
+--
 -- >>> let v = var (const "Hello ") `mappend` var (const "World!")
 -- >>> testVarOver v [()]
 -- "Hello World!"
-instance (Applicative m, Monad m, Monoid b) => Monoid (VarT m a b) where
+instance (Applicative m, Monoid b) => Monoid (VarT m a b) where
   mempty = pure mempty
   mappend = liftA2 mappend
 
--- | Streams can be written as numbers.
+-- | Vars can be written as numbers.
 --
 -- >>> let v = 1 >>> accumulate (+) 0
 -- >>> testVarOver v [(),(),()]
 -- 1
 -- 2
 -- 3
-instance (Applicative m, Monad m, Num b) => Num (VarT m a b) where
+instance (Monad m, Num b) => Num (VarT m a b) where
     (+) = liftA2 (+)
     (-) = liftA2 (-)
     (*) = liftA2 (*)
@@ -176,14 +223,14 @@
     signum = fmap signum
     fromInteger = pure . fromInteger
 
--- | Streams can be written as floats.
+-- | Vars can be written as floats.
 --
 -- >>> let v = pi >>> accumulate (*) 1 >>> arr round
 -- >>> testVarOver v [(),(),()]
 -- 3
 -- 10
 -- 31
-instance (Applicative m, Monad m, Floating b) => Floating (VarT m a b) where
+instance (Monad m, Floating b) => Floating (VarT m a b) where
     pi = pure pi
     exp = fmap exp
     log = fmap log
@@ -191,26 +238,26 @@
     cos = fmap cos; cosh = fmap cosh; acos = fmap acos; acosh = fmap acosh
     atan = fmap atan; atanh = fmap atanh
 
--- | Streams can be written as fractionals.
+-- | Vars can be written as fractionals.
 --
 -- >>> let v = 2.5 >>> accumulate (/) 10
 -- >>> testVarOver v [(),(),()]
 -- 4.0
 -- 1.6
 -- 0.64
-instance (Applicative m, Monad m, Fractional b) => Fractional (VarT m a b) where
+instance (Monad m, Fractional b) => Fractional (VarT m a b) where
     (/) = liftA2 (/)
     fromRational = pure . fromRational
 --------------------------------------------------------------------------------
 -- $creation
--- You can create a pure stream by lifting a function @(a -> b)@
+-- You can create a pure var by lifting a function @(a -> b)@
 -- with 'var':
 --
 -- > arr (+1) == var (+1) :: VarT m Int Int
 --
 -- 'var' is a parameterized version of 'arr'.
 --
--- You can create a monadic stream by lifting a monadic computation
+-- You can create a monadic var by lifting a monadic computation
 -- @(a -> m b)@ using 'varM':
 --
 -- @
@@ -220,7 +267,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 streams are stepped and sampled:
+-- over how vars are stepped and sampled:
 --
 -- > delay :: Monad m => b -> VarT m a b -> VarT m a b
 -- > delay b v = VarT $ \a -> return (b, go a v)
@@ -228,37 +275,37 @@
 -- >                                      return (b', go a' v'')
 -- >
 --------------------------------------------------------------------------------
--- | Lift a pure computation to a stream. This is 'arr' parameterized over the
+-- | Lift a pure computation to a var. This is 'arr' parameterized over the
 -- @a `VarT m` b@ arrow.
 var :: Applicative m => (a -> b) -> VarT m a b
-var f = VarT $ \(!a) -> pure (f a, var f)
+var f = VarT $ \a -> pure (f a, var f)
 
--- | Lift a monadic computation to a stream. This is
+-- | Lift a monadic computation to a var. This is
 -- <http://hackage.haskell.org/package/arrow-list-0.7/docs/Control-Arrow-Kleisli-Class.html#v:arrM arrM>
 -- parameterized over the @a `VarT m` b@ arrow.
 varM :: Monad m => (a -> m b) -> VarT m a b
-varM f = VarT $ \(!a) -> do
+varM f = VarT $ \a -> do
     b <- f a
     return (b, varM f)
 
--- | Lift a constant value to a stream.
-done :: (Applicative m, Monad m) => b -> VarT m a b
-done b = VarT $ \(!_) -> return (b, done b)
+-- | Lift a constant value to a var.
+done :: Applicative m => b -> VarT m a b
+done = var . const
 
--- | Create a stream from a state transformer.
+-- | Create a var from a state transformer.
 mkState :: Monad m
         => (a -> s -> (b, s)) -- ^ state transformer
         -> s -- ^ intial state
         -> VarT m a b
-mkState f s = VarT $ \(!a) -> do
+mkState f s = VarT $ \a -> do
   let (b', s') = f a s
   return (b', mkState f s')
 --------------------------------------------------------------------------------
 -- $composition
--- You can compose streams together using Category's '>>>' and '<<<'. The "right
--- plug" ('>>>') takes the output from a stream on the left and "plugs" it into
--- the input of the stream on the right. The "left plug" does the same thing in
--- the opposite direction. This allows you to write streams that read
+-- You can compose vars together using Category's '>>>' and '<<<'. The "right
+-- plug" ('>>>') takes the output from a var on the left and "plugs" it into
+-- the input of the var on the right. The "left plug" does the same thing in
+-- the opposite direction. This allows you to write vars that read
 -- naturally.
 --------------------------------------------------------------------------------
 --------------------------------------------------------------------------------
@@ -274,12 +321,12 @@
 --
 -- >>> print $ foldl (++) [] $ words "hey there man"
 -- "heythereman"
-accumulate :: (Monad m, Applicative m) => (c -> b -> c) -> c -> VarT m b c
-accumulate f b = VarT $ \(!a) -> do
+accumulate :: Monad m => (c -> b -> c) -> c -> VarT m b c
+accumulate f b = VarT $ \a -> do
     let b' = f b a
     return (b', accumulate f b')
 
--- | Delays the given stream by one sample using the argument as the first
+-- | Delays the given var by one sample using the argument as the first
 -- sample.
 --
 -- >>> testVarOver (delay 0 id) [1,2,3]
@@ -287,21 +334,21 @@
 -- 1
 -- 2
 --
--- This enables the programmer to create streams that depend on
+-- This enables the programmer to create vars that depend on
 -- themselves for values. For example:
 --
 -- >>> let v = delay 0 v + 1 in testVarOver v [1,1,1]
 -- 1
 -- 2
 -- 3
-delay :: (Monad m, Applicative m) => b -> VarT m a b -> VarT m a b
-delay b v = VarT $ \(!a) -> return (b, go a v)
-    where go a v' = VarT $ \(!a') -> do (b', v'') <- runVarT v' a
-                                        return (b', go a' v'')
+delay :: Monad m => b -> VarT m a b -> VarT m a b
+delay b v = VarT $ \a -> return (b, go a v)
+    where go a v' = VarT $ \a' -> do (b', v'') <- runVarT v' a
+                                     return (b', go a' v'')
 --------------------------------------------------------------------------------
 -- $running
--- To sample a stream simply run it in the desired monad with
--- 'runVarT'. This will produce a sample value and a new stream.
+-- To sample a var simply run it in the desired monad with
+-- 'runVarT'. This will produce a sample value and a new var.
 --
 -- >>> :{
 -- do let v0 = accumulate (+) 0
@@ -316,33 +363,33 @@
 -- 2
 -- 4
 --------------------------------------------------------------------------------
--- | 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.
+-- | Iterate a var over a list of input until all input is consumed,
+-- then iterate the var using one single input. Returns the resulting
+-- output value and the new var.
 --
 -- >>> let Identity (outputs, _) = stepMany (accumulate (+) 0) [1,1,1] 1
 -- >>> print outputs
 -- 4
-stepMany :: (Monad m, Functor m) => VarT m a b -> [a] -> a -> m (b, VarT m a b)
-stepMany v [] e = runVarT v e
+stepMany :: (Monad 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
+-- | Run the var over the input values, gathering the output values in a
 -- list.
 --
 -- >>> let Identity (outputs, _) = scanVar (accumulate (+) 0) [1,1,1,1]
 -- >>> print outputs
 -- [1,2,3,4]
-scanVar :: (Applicative m, Monad m) => VarT m a b -> [a] -> m ([b], VarT m a b)
+scanVar :: Monad m => VarT m a b -> [a] -> m ([b], VarT m a b)
 scanVar v = foldM f ([], v)
     where f (outs, v') a = do (b, v'') <- runVarT v' a
                               return (outs ++ [b], v'')
 --------------------------------------------------------------------------------
 -- Testing and debugging
 --------------------------------------------------------------------------------
--- | Trace the sample value of a stream and pass it along as output. This is
--- very useful for debugging graphs of streams. The (v|vs|vf)trace family of
--- streams use 'Debug.Trace.trace' under the hood, so the value is only traced
+-- | Trace the sample value of a var and pass it along as output. This is
+-- very useful for debugging graphs of vars. The (v|vs|vf)trace family of
+-- vars use 'Debug.Trace.trace' under the hood, so the value is only traced
 -- when evaluated.
 --
 -- >>> let v = id >>> vtrace
@@ -356,8 +403,9 @@
 vtrace :: (Applicative a, Show b) => VarT a b b
 vtrace = vstrace ""
 
--- | Trace the sample value of a stream with a prefix and pass the sample along
--- as output. This is very useful for debugging graphs of streams.
+
+-- | Trace the sample value of a var with a prefix and pass the sample along
+-- as output. This is very useful for debugging graphs of vars.
 --
 -- >>> let v = id >>> vstrace "test: "
 -- >>> testVarOver v [1,2,3]
@@ -371,7 +419,7 @@
 vstrace s = vftrace ((s ++) . show)
 
 -- | Trace the sample value using a custom show-like function. This is useful
--- when you would like to debug a stream that uses values that don't have show
+-- when you would like to debug a var that uses values that don't have show
 -- instances.
 --
 -- >>> newtype NotShowableInt = NotShowableInt { unNotShowableInt :: Int }
@@ -387,9 +435,9 @@
 vftrace :: Applicative a => (b -> String) -> VarT a b b
 vftrace f = var $ \b -> trace (f b) b
 
--- | Run a stream in IO over some input, printing the output each step. This is
+-- | Run a var in IO over some input, printing the output each step. This is
 -- the function we've been using throughout this documentation.
-testVarOver :: (Applicative m, Monad m, MonadIO m, Show b)
+testVarOver :: (Monad m, MonadIO m, Show b)
             => VarT m a b -> [a] -> m ()
 testVarOver v xs = fst <$> scanVar v xs >>= mapM_ (liftIO . print)
 --------------------------------------------------------------------------------
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
@@ -1,8 +1,9 @@
+{-# LANGUAGE LambdaCase #-}
 -- |
 --   Module:     Control.Varying.Event
 --   Copyright:  (c) 2015 Schell Scivally
 --   License:    MIT
---   Maintainer: Schell Scivally <schell.scivally@synapsegroup.com>
+--   Maintainer: Schell Scivally <schell@takt.com>
 --
 --  An event stream is simply a stream of @Maybe a@. This kind of stream is
 --  considered to be only defined at those occurances of @Just a@. Events
@@ -18,10 +19,7 @@
 --  is running.  For more info on switching and sequencing streams with events
 --  please check out 'Control.Varying.Spline', which lets you chain together
 --  sequences of values and events using a familiar do-notation.
-{-# LANGUAGE CPP #-}
-#if __GLASGOW_HASKELL__ >= 800 
-{-# OPTIONS_GHC -Wno-redundant-constraints #-}
-#endif
+
 module Control.Varying.Event
   ( -- * Event constructors (synonyms of Maybe)
     Event
@@ -48,21 +46,18 @@
   , never
   , before
   , after
+    -- * Switching
+  , switch
     -- * Bubbling
   , onlyWhen
   , onlyWhenE
   ) where
 
-import Prelude hiding (until)
-import Control.Varying.Core
-import Control.Monad
-import Data.Foldable (foldl')
-
--- stuff for FAMP
-#if __GLASGOW_HASKELL__ < 709
-import Control.Applicative
-import Data.Function
-#endif
+import           Control.Applicative
+import           Control.Monad
+import           Control.Varying.Core
+import           Data.Foldable        (foldl')
+import           Prelude              hiding (until)
 
 type Event = Maybe
 
@@ -95,7 +90,7 @@
 -- @
 -- 'use' b 'onTrue' :: 'Monad' m => 'VarT' m 'Bool' ('Event' b)
 -- @
-onTrue :: (Applicative m, Monad m) => VarT m Bool (Event ())
+onTrue :: Monad m => VarT m Bool (Event ())
 onTrue = var $ \b -> if b then Just () else Nothing
 
 -- | Triggers an @'Event' a@ when the input is distinct from the previous
@@ -104,7 +99,7 @@
 -- @
 -- 'use' b 'onUnique' :: ('Eq' x, 'Monad' m) => 'VarT' m x ('Event' b)
 -- @
-onUnique :: (Applicative m, Monad m, Eq a) => VarT m a (Event a)
+onUnique :: (Monad m, Eq a) => VarT m a (Event a)
 onUnique = VarT $ \a -> return (Just a, trigger a)
     where trigger a' = VarT $ \a'' -> let e = if a' == a''
                                              then Nothing
@@ -125,6 +120,7 @@
                  in return (acc', foldStream f acc')
       Nothing -> return (acc, foldStream f acc)
 
+
 -- | 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.
@@ -132,13 +128,26 @@
 -- @
 -- time '>>>' 'Control.Varying.Time.after' 3 '>>>' 'startingWith' 0
 -- @
-startWith, startingWith :: (Applicative m, Monad m) => a -> VarT m (Event a) a
-startWith = foldStream (\_ a -> a)
+--
+-- >>> :{
+-- let v = onWhen (== 3) >>> startingWith 0
+-- in testVarOver v [0, 1, 2, 3, 4]
+-- >>> :}
+-- 0
+-- 0
+-- 0
+-- 3
+-- 3
+startWith, startingWith
+  :: Monad m
+  => a
+  -> VarT m (Event a) a
+startWith    = foldStream (\_ a -> a)
 startingWith = startWith
 
 -- | Stream through some number of successful 'Event's and then inhibit
 -- forever.
-takeE :: (Applicative m, Monad m)
+takeE :: Monad m
       => Int -> VarT m a (Event b) -> VarT m a (Event b)
 takeE 0 _ = never
 takeE n ve = VarT $ \a -> do
@@ -148,7 +157,7 @@
         Just  b -> return (Just b, takeE (n-1) ve')
 
 -- | Inhibit the first n occurences of an 'Event'.
-dropE :: (Applicative m, Monad m)
+dropE :: Monad m
       => Int -> VarT m a (Event b) -> VarT m a (Event b)
 dropE 0 ve = ve
 dropE n ve = VarT $ \a -> do
@@ -158,7 +167,7 @@
         Just  _ -> return (Nothing, dropE (n-1) ve')
 
 -- | Inhibit all 'Event's that don't pass the predicate.
-filterE :: (Applicative m, Monad m)
+filterE :: Monad m
         => (b -> Bool) -> VarT m a (Event b) -> VarT m a (Event b)
 filterE p v = (join . (check <$>)) <$> v
   where check b = if p b then Just b else Nothing
@@ -167,7 +176,7 @@
 --------------------------------------------------------------------------------
 -- | Combine two 'Event' streams. Produces an event only when both streams proc
 -- at the same time.
-bothE :: (Applicative m, Monad m)
+bothE :: Monad m
        => (a -> b -> c) -> VarT m a (Event a) -> VarT m a (Event b)
        -> VarT m a (Event c)
 bothE f va vb = (\ea eb -> f <$> ea <*> eb) <$> va <*> vb
@@ -175,7 +184,7 @@
 -- | 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 leftmost stream.
-anyE :: (Applicative m, Monad m) => [VarT m a (Event b)] -> VarT m a (Event b)
+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
@@ -185,7 +194,7 @@
 -- Primitive event streams
 --------------------------------------------------------------------------------
 -- | Produce the given event value once and then inhibit forever.
-once :: (Applicative m, Monad m) => b -> VarT m a (Event b)
+once :: Monad m => b -> VarT m a (Event b)
 once b = VarT $ \_ -> return (Just b, never)
 
 -- | Never produces any 'Event' values.
@@ -193,7 +202,7 @@
 -- @
 -- 'never' = 'pure' 'Nothing'
 -- @
-never :: (Applicative m, Monad m) => VarT m b (Event c)
+never :: Monad m => VarT m b (Event c)
 never = pure Nothing
 
 -- | Produces 'Event's with the initial value forever.
@@ -201,27 +210,69 @@
 -- @
 -- 'always' e = 'pure' ('Event' e)
 -- @
-always :: (Applicative m, Monad m) => b -> VarT m a (Event b)
+always :: Monad m => b -> VarT m a (Event b)
 always = pure . Just
 
 -- | Emits events before accumulating t of input dt.
 -- Note that as soon as we have accumulated >= t we stop emitting events
 -- and therefore an event will never be emitted exactly at time == t.
-before :: (Applicative m, Monad m, Num t, Ord t) => t -> VarT m t (Event t)
+before :: (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,
 -- 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) 
+after :: (Monad m, Num t, Ord t) => t -> VarT m t (Event t)
+after t = accumulate (+) 0 >>> onWhen (>= t)
+
 --------------------------------------------------------------------------------
+-- Switching
+--------------------------------------------------------------------------------
+-- | Higher-order switching.
+-- Use an event stream of value streams and produces event values of the latest
+-- produced value stream. Switches to a new value stream each time one is
+-- produced. The currently used value stream maintains local state until the
+-- outer event stream produces a new value stream.
+--
+-- In this example we're sequencing the value streams we'd like to use and then
+-- switching them when the outer event stream fires.
+--
+-- >>> import Control.Varying.Spline
+-- >>> :{
+-- let v :: VarT IO () (Event Int)
+--     v = switch $ flip outputStream Nothing $ do
+--           step $ Just $ 1 >>> accumulate (+) 0
+--           step Nothing
+--           step Nothing
+--           step $ Just 5
+--           step Nothing
+-- in testVarOver v [(), (), (), (), ()] -- testing over five frames
+-- >>> :}
+-- Just 1
+-- Just 2
+-- Just 3
+-- Just 5
+-- Just 5
+switch
+  :: Monad m
+  => VarT m a (Event (VarT m a b))
+  -> VarT m a (Event b)
+switch = switchGo $ pure Nothing
+  where switchGo vInner v = VarT $ \a -> runVarT v a >>= \case
+          (Nothing, vOuter) -> do
+            (mayB, vInner1) <- runVarT vInner a
+            return (mayB, switchGo vInner1 vOuter)
+          (Just vInner2, vOuter) -> do
+            (mayB, vInner3) <- runVarT (Just <$> vInner2) a
+            return (mayB, switchGo vInner3 vOuter)
+
+--------------------------------------------------------------------------------
 -- Bubbling
 --------------------------------------------------------------------------------
 -- | Produce events of a stream @v@ only when an event stream @h@ produces an
 -- event.
 -- @v@ and @h@ maintain state while cold.
-onlyWhenE :: (Applicative m, Monad m)
+onlyWhenE :: Monad m
           => VarT m a b -- ^ @v@ - The value stream
           -> VarT m a (Event c) -- ^ @h@ - The event stream
           -> VarT m a (Event b)
@@ -235,7 +286,7 @@
 -- | Produce 'Event's of a value stream @v@ only when its input value passes a
 -- predicate @f@.
 -- @v@ maintains state while cold.
-onlyWhen :: (Applicative m, Monad m)
+onlyWhen :: Monad m
          => VarT m a b -- ^ @v@ - The value stream
          -> (a -> Bool) -- ^ @f@ - The predicate to run on @v@'s input values.
          -> VarT m a (Event b)
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
@@ -2,24 +2,20 @@
 --   Module:     Control.Varying.Spline
 --   Copyright:  (c) 2015 Schell Scivally
 --   License:    MIT
---   Maintainer: Schell Scivally <efsubenovex@gmail.com>
+--   Maintainer: Schell Scivally <schell@takt.com>
 --
 --  Using splines we can easily create continuous streams from discontinuous
---  streams. A spline is a monadic layer on top of streams. The idea is that we
---  use a monad to splice together sequences of streams that eventually end. This
---  means taking two streams - an output stream and an event stream - combining
---  them into a temporarily producing stream. Once that "stream pair" inhibits
---  (stops producing), the computation completes and returns a result value. That
---  result value is then used to determine the next spline in the sequence.
-{-# LANGUAGE GADTs            #-}
+--  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 a monad to
+--  "run a stream switched by events". This means taking two streams - an output
+--  stream and an event stream, and combining them into a temporarily producing
+--  stream. Once that "stream pair" inhibits, the computation completes and
+--  returns a result value. That result value is then used to determine the next
+--  spline in the sequence.
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TupleSections    #-}
+{-# LANGUAGE GADTs            #-}
 {-# LANGUAGE LambdaCase       #-}
-{-# LANGUAGE BangPatterns     #-}
-{-# LANGUAGE CPP              #-}
-#if __GLASGOW_HASKELL__ >= 800
-{-# OPTIONS_GHC -Wno-redundant-constraints #-}
-#endif
+{-# LANGUAGE TupleSections    #-}
 module Control.Varying.Spline
   ( -- * Spline
     Spline
@@ -28,6 +24,7 @@
     -- * Creating streams from splines
   , outputStream
     -- * Creating splines from streams
+  , fromEvent
   , untilProc
   , whileProc
   , untilEvent
@@ -48,19 +45,13 @@
     -- $proofs
   ) where
 
-import Control.Varying.Core
-import Control.Varying.Event
-import Control.Monad
-import Control.Monad.Trans.Class
-import Control.Monad.IO.Class
-import Data.Functor.Identity
-import Data.Monoid
-
--- stuff for FAMP
-#if __GLASGOW_HASKELL__ < 709
-import Control.Applicative
-import Data.Function
-#endif
+import           Control.Monad
+import           Control.Monad.IO.Class
+import           Control.Monad.Trans.Class
+import           Control.Varying.Core
+import           Control.Varying.Event
+import           Data.Functor.Identity
+import           Data.Monoid
 
 -- $setup
 -- >>> import Control.Varying.Time
@@ -76,7 +67,7 @@
 -- can be used to determine the next spline to run. Using 'outputStream' we can
 -- then fuse these piecewise continuous (but otherwise discontinuous) streams
 -- into one continuous stream of type @VarT m a b@. Alternatively you can simply
--- poll the network until it ends using 'runSplineT'.  
+-- poll the network until it ends using 'runSplineT'.
 newtype SplineT a b m c =
   SplineT { runSplineT :: a -> m (Either c (b, SplineT a b m c)) }
 
@@ -87,13 +78,13 @@
 -- >>> :{
 -- let s0 = pure "first" `untilEvent` (1 >>> after 2)
 --     s = do str <- fmap show s0
---            step str  
---     v = outputStream s "" 
+--            step str
+--     v = outputStream s ""
 -- in testVarOver v [(),()]
 -- >>> :}
 -- "first"
 -- "(\"first\",2)"
-instance (Applicative m, Monad m) => Functor (SplineT a b m) where
+instance Monad m => Functor (SplineT a b m) where
   fmap f (SplineT s) = SplineT $ s >=> \case
     Left c        -> return $ Left $ f c
     Right (b, s1) -> return $ Right (b, fmap f s1)
@@ -102,7 +93,7 @@
 -- then uses that value to run the next spline.
 --
 -- Note - checkout the <$proofs proofs>
-instance (Applicative m, Monad m) => Monad (SplineT a b m) where
+instance Monad m => Monad (SplineT a b m) where
   return = SplineT . const . return . Left
   (SplineT s0) >>= f = SplineT $ g s0
     where g s a = do e <- s a
@@ -110,7 +101,7 @@
                        Left  c               -> runSplineT (f c) a
                        Right (b, SplineT s1) -> return $ Right (b, SplineT $ g s1)
 
--- A spline responds to 'pure' by returning a spline that never produces an
+-- | 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.
@@ -122,7 +113,7 @@
 --   x <- sx
 --   return $ f x
 -- @
-instance (Applicative m, Monad m) => Applicative (SplineT a b m) where
+instance Monad m => Applicative (SplineT a b m) where
   pure = return
   sf <*> sx = do
     f <- sf
@@ -130,10 +121,10 @@
     return $ f x
 
 -- | A spline is a transformer by running the effect and immediately concluding,
--- using the effect's result as the result value. 
--- 
+-- using the effect's result as the result value.
+--
 -- >>> :{
--- let s = do () <- lift $ print "Hello"  
+-- let s = do () <- lift $ print "Hello"
 --            step 2
 --     v = outputStream s 0
 -- in testVarOver v [()]
@@ -141,11 +132,11 @@
 -- "Hello"
 -- 2
 instance MonadTrans (SplineT a b) where
-  lift f = SplineT $ const $ f >>= return . Left
+  lift f = SplineT $ const $ Left <$> 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.
-instance (Applicative m, Monad m, MonadIO m) => MonadIO (SplineT a b m) where
+instance (Monad m, MonadIO m) => MonadIO (SplineT a b m) where
   liftIO = lift . liftIO
 
 -- | A SplineT monad parameterized with Identity that takes input of type @a@,
@@ -157,7 +148,7 @@
 -- function takes a default value to use as the "last known value".
 --
 -- >>> :{
--- let s :: SplineT () String IO ()  
+-- let s :: SplineT () String IO ()
 --     s = do first <- pure "accumulating until 3" `_untilEvent` (1 >>> after 3)
 --            secnd <- pure "accumulating until 4" `_untilEvent` (1 >>> after 4)
 --            if first + secnd == 7
@@ -172,7 +163,7 @@
 -- "accumulating until 4"
 -- "accumulating until 4"
 -- "done"
-outputStream :: (Applicative m, Monad m)
+outputStream :: Monad m
              => SplineT a b m c -> b -> VarT m a b
 outputStream (SplineT s0) b0 = VarT $ f s0 b0
   where f s b a = do e <- s a
@@ -182,21 +173,29 @@
 
 -- | Run the spline over the input values, gathering the output values in a
 -- list.
-scanSpline :: (Applicative m, Monad m)
+scanSpline :: Monad m
            => SplineT a b m c -> b -> [a] -> m [b]
 scanSpline s b = fmap fst <$> scanVar (outputStream s b)
 
+-- | Create a spline from an event stream.
+fromEvent :: Monad m => VarT m a (Event b) -> SplineT a (Event b) m b
+fromEvent ve = SplineT $ \a -> do
+  (e, ve1) <- runVarT ve a
+  return $ case e of
+    Just b  -> Left b
+    Nothing -> Right (Nothing, fromEvent ve1)
+
 -- | Create a spline from an event stream. Outputs 'noevent' until the event
 -- stream procs, at which point the spline concludes with the event value.
-untilProc :: (Applicative m, Monad m) => VarT m a (Event b) -> SplineT a (Event b) m b
-untilProc ve = SplineT $ runVarT ve >=> return . \case 
+untilProc :: Monad m => VarT m a (Event b) -> SplineT a (Event b) m b
+untilProc ve = SplineT $ runVarT ve >=> return . \case
   (Just b,    _) -> Left b
   (Nothing, ve1) -> Right (Nothing, untilProc ve1)
 
 -- | Create a spline from an event stream. Outputs @b@ until the event stream
 -- inhibits, at which point the spline concludes with @()@.
-whileProc :: (Applicative m, Monad m) => VarT m a (Event b) -> SplineT a b m () 
-whileProc ve = SplineT $ runVarT ve >=> return . \case 
+whileProc :: Monad m => VarT m a (Event b) -> SplineT a b m ()
+whileProc ve = SplineT $ runVarT ve >=> return . \case
   (Just b, ve1) -> Right (b, whileProc ve1)
   (Nothing,  _) -> Left ()
 
@@ -204,25 +203,26 @@
 -- uses the stream's values as its own output values. The spline will run until
 -- the event stream produces an event, at that point the last known output
 -- value and the event value are tupled and returned as the spline's result.
-untilEvent :: (Applicative m, Monad m)
+untilEvent :: Monad m
            => VarT m a b -> VarT m a (Event c) -> SplineT a b m (b,c)
 untilEvent v ve = SplineT $ f ((,) <$> v <*> ve)
-  where f vve = runVarT vve >=> return . \case 
-                  ((b, Nothing), vve1) -> Right (b, SplineT $ f vve1)
-                  ((b, Just c),     _) -> Left (b, c)
+  where f vve a = do t <-runVarT vve a
+                     return $ case t of
+                       ((b, Nothing), vve1) -> Right (b, SplineT $ f vve1)
+                       ((b, Just c),    _)  -> Left (b, c)
 
 -- | A variant of 'untilEvent' that results in the last known output value.
-untilEvent_ :: (Applicative m, Monad m)
+untilEvent_ :: Monad m
             => VarT m a b -> VarT m a (Event c) -> SplineT a b m b
 untilEvent_ v ve = fst <$> untilEvent v ve
 
 -- | A variant of 'untilEvent' that results in the event steam's event value.
-_untilEvent :: (Applicative m, Monad m)
+_untilEvent :: Monad m
             => VarT m a b -> VarT m a (Event c) -> SplineT a b m c
 _untilEvent v ve = snd <$> untilEvent v ve
 
 -- | A variant of 'untilEvent' that discards both the output and event values.
-_untilEvent_ :: (Applicative m, Monad m)
+_untilEvent_ :: Monad m
              => VarT m a b -> VarT m a (Event c) -> SplineT a b m ()
 _untilEvent_ v ve = void $ _untilEvent v ve
 
@@ -241,7 +241,7 @@
 -- "route 666"
 -- "Left 2"
 -- "Left 2"
-race :: (Applicative m, Monad m)
+race :: Monad m
      => (a -> b -> c) -> SplineT i a m d -> SplineT i b m e
      -> SplineT i c m (Either d e)
 race f sa0 sb0 = SplineT (g sa0 sb0)
@@ -258,7 +258,7 @@
 -- >>> :{
 -- let ss = [ pure "hey "   `_untilEvent` (1 >>> after 5)
 --          , pure "there"  `_untilEvent` (1 >>> after 3)
---          , pure "!"      `_untilEvent` (1 >>> after 2) 
+--          , pure "!"      `_untilEvent` (1 >>> after 2)
 --          ]
 --     s = do winner <- raceAny ss
 --            step $ show winner
@@ -267,7 +267,7 @@
 -- >>> :}
 -- "hey there!"
 -- "2"
-raceAny :: (Applicative m, Monad m, Monoid b)
+raceAny :: (Monad m, Monoid b)
          => [SplineT a b m c] -> SplineT a b m c
 raceAny [] = pure mempty `_untilEvent` never
 raceAny ss = SplineT $ f [] (map runSplineT ss) mempty
@@ -289,8 +289,8 @@
 -- >>> :}
 -- "hey there!"
 -- "hey "
--- "(3,2)" 
-merge :: (Applicative m, Monad m)
+-- "(3,2)"
+merge :: Monad m
      => (b -> b -> b)
      -> SplineT a b m c -> SplineT a b m d -> SplineT a b m (c, d)
 merge apnd s1 s2 = SplineT $ f s1 s2
@@ -324,11 +324,11 @@
 --            step $ x + 1
 -- in testVarOver (outputStream s 666) [(),(),(),()]
 -- >>> :}
--- 0 
+-- 0
 -- 1
 -- 2
 -- 3
-capture :: (Applicative m, Monad m)
+capture :: Monad m
         => SplineT a b m c -> SplineT a b m (Event b, c)
 capture = SplineT . f Nothing
     where f mb s = runSplineT s >=> return . \case
@@ -347,19 +347,19 @@
 -- "there"
 -- "friend"
 -- "friend"
-step :: (Applicative m, Monad m) => b -> SplineT a b m ()
+step :: Monad m => b -> SplineT a b m ()
 step b = SplineT $ const $ return $ Right (b, return ())
 
 -- | Map the output value of a spline.
 --
 -- >>> :{
--- let s = mapOutput (pure show) $ step 1 >> step 2 >> step 3  
--- in testVarOver (outputStream s "") [(),(),()]    
+-- let s = mapOutput (pure show) $ step 1 >> step 2 >> step 3
+-- in testVarOver (outputStream s "") [(),(),()]
 -- >>> :}
 -- "1"
 -- "2"
 -- "3"
-mapOutput :: (Applicative m, Monad m)
+mapOutput :: Monad m
           => VarT m a (b -> t) -> SplineT a b m c -> SplineT a t m c
 mapOutput vf0 s0 = SplineT $ g vf0 s0
     where g vf s a = do
@@ -369,7 +369,7 @@
               Right (b, s1) -> Right (f b, SplineT $ g vf1 s1)
 
 -- | Map the input value of a spline.
-adjustInput :: (Applicative m, Monad m)
+adjustInput :: Monad m
             => VarT m a (a -> r) -> SplineT r b m c -> SplineT a b m c
 adjustInput vf0 s = SplineT $ g vf0 s
   where g vf sx a = do
@@ -379,7 +379,7 @@
            Right (b, sx1) -> Right (b, SplineT $ g vf1 sx1)
 
 --------------------------------------------------------------------------------
--- $proofs 
+-- $proofs
 -- ==Left Identity
 -- > k =<< return c = k c
 --
@@ -501,4 +501,4 @@
 -- ==Application
 -- > (m >>= f) >>= g = m >>= (\x -> f x >>= g)
 
--- TODO
+-- TODO: Finish the rest of the hand proofs
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
@@ -2,7 +2,7 @@
 --   Module:     Control.Varying.Tween
 --   Copyright:  (c) 2016 Schell Scivally
 --   License:    MIT
---   Maintainer: Schell Scivally <efsubenovex@gmail.com>
+--   Maintainer: Schell Scivally <schell@takt.com>
 --
 --   Tweening is a technique of generating intermediate samples of a type
 --   __between__ a start and end value. By sampling a running tween
@@ -51,18 +51,20 @@
     -- $writing
   ) where
 
-import Control.Varying.Core
-import Control.Varying.Event
-import Control.Varying.Spline
-import Control.Monad.Trans.State
-import Control.Applicative
-import Data.Functor.Identity
+import           Control.Monad             (void)
+import           Control.Monad.Trans.State (StateT, evalStateT, get, put,
+                                            runStateT)
+import           Control.Varying.Core      (VarT (..), done)
+import           Control.Varying.Spline    (SplineT (..), mapOutput, scanSpline,
+                                            untilEvent_)
+import           Control.Varying.Event     (after)
+import           Data.Functor.Identity     (Identity)
 
 --------------------------------------------------------------------------------
 -- $lerping
 -- These pure functions take a `c` (total change in value, ie end - start),
 -- `t` (percent of duration completion) and `b` (start value) and result in
--- and interpolation of a value. To see what these look like please check
+-- an interpolation of a value. To see what these look like please check
 -- out http://www.gizma.com/easing/.
 --------------------------------------------------------------------------------
 -- | Ease in quadratic.
@@ -127,28 +129,32 @@
 
 -- | Ease linear.
 linear :: (Floating t, Real f) => Easing t f
-linear c t b = c * (realToFrac t) + b
+linear c t b = c * realToFrac t + b
 
+-- TODO: Don't use StateT for leftover time in Tweens.
+-- This creates a funky state where running two tween splines together
+-- causes leftover time interplay. Think about continuations or something.
+
 type TweenT f t m = SplineT f t (StateT f m)
 type Tween f t = TweenT f t Identity
 
-runTweenT :: (Monad m, Num f)
-          => TweenT f t m x -> f -> f -> m (Either x (t, TweenT f t m x), f)
+runTweenT :: TweenT f t m x -> f -> f -> m (Either x (t, TweenT f t m x), f)
 runTweenT s dt = runStateT (runSplineT s dt)
 
-scanTween :: (Functor m, Applicative m, Monad m, Num f)
+scanTween :: (Monad m, Num f)
           => TweenT f t m a -> t -> [f] -> m [t]
 scanTween s t dts = evalStateT (scanSpline s t dts) 0
 
 -- | Converts a tween into a continuous value stream. This is the tween version
 -- of `outputStream`.
-tweenStream :: (Applicative m, Monad m, Num f)
+tweenStream :: (Monad m, Num f)
             => TweenT f t m x -> t -> VarT m f t
 tweenStream s0 t0 = VarT $ f s0 t0 0
   where f s t l i = do (e, l1) <- runTweenT s i l
                        case e of
-                         Left _ -> return (t, done t)
+                         Left _        -> return (t, done t)
                          Right (b, s1) -> return (b, VarT $ f s1 b l1)
+
 --------------------------------------------------------------------------------
 -- $creation
 -- The most direct route toward tweening values is to use 'tween'
@@ -161,12 +167,12 @@
 -- | 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.
--- Keep in mind `tween` must be fed time deltas, not absolute time or
+-- Keep in mind that `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` concludes returning the latest output value.
-tween :: (Applicative m, Monad m, Real f, Fractional f, Real t, Fractional t)
+tween :: (Monad m, Real t, Real f, Fractional f)
       => Easing t f -> t -> t -> f -> TweenT f t m t
 tween f start end dur = SplineT g
   where c = end - start
@@ -190,26 +196,26 @@
 -- tween f a b c >> return ()
 -- @
 --
-tween_ :: (Applicative m, Monad m, Real t, Fractional t, Real f, Fractional f)
+tween_ :: (Monad m, Real t, Real f, Fractional f)
        => Easing t f -> t -> t -> f -> TweenT f t m ()
-tween_ f a b c = tween f a b c >> return ()
+tween_ f a b c = Control.Monad.void (tween f a b c)
 
 -- | A version of 'tween' that maps its output using the given constant
 -- function.
 -- @
 -- withTween ease from to dur f = mapOutput (pure f) $ tween ease from to dur
 -- @
-withTween :: (Applicative m, Monad m, Real t, Fractional t, Real a, Fractional a)
+withTween :: (Monad m, Real t, Real a, Fractional a)
           => Easing t a -> t -> t -> a -> (t -> x) -> TweenT a x m t
 withTween ease from to dur f = mapOutput (pure f) $ tween ease from to dur
 
 -- | A version of 'withTween' that discards its output.
-withTween_ :: (Applicative m, Monad m, Real t, Fractional t, Real a, Fractional a)
+withTween_ :: (Monad m, Real t, Real a, Fractional a)
            => Easing t a -> t -> t -> a -> (t -> x) -> TweenT a x m ()
-withTween_ ease from to dur f = withTween ease from to dur f >> return ()
+withTween_ ease from to dur f = Control.Monad.void (withTween ease from to dur f)
 
 -- | Creates a tween that performs no interpolation over the duration.
-constant :: (Applicative m, Monad m, Num t, Ord t)
+constant :: (Monad m, Num t, Ord t)
          => a -> t -> TweenT t a m a
 constant value duration = pure value `untilEvent_` after duration
 --------------------------------------------------------------------------------
@@ -229,6 +235,6 @@
 -- duration that has elapsed and `b` is the start value.
 --
 -- To make things simple only numerical values can be tweened and the type
--- of time deltas much match the tween's value type. This may change in the
+-- of time deltas must match the tween's value type. This may change in the
 -- future :)
 type Easing t f = t -> f -> t -> t
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,8 +1,4 @@
-{-# LANGUAGE CPP #-}
-
-#if __GLASGOW_HASKELL__ > 710 
-{-# OPTIONS_GHC -Wno-redundant-constraints #-}
-#endif
+{-# LANGUAGE ScopedTypeVariables #-}
 
 module Main where
 
@@ -13,26 +9,23 @@
 import Data.Functor.Identity
 import Data.Time.Clock
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative
-#endif
-
 main :: IO ()
 main = hspec $ do
-  describe "before" $ 
+  describe "before" $
     it "should produce events before a given step" $ do
       let varEv :: Var () (Maybe Int)
           varEv = 1 >>> before 3
           scans = fst $ runIdentity $ scanVar varEv $ replicate 4 ()
       scans `shouldBe` [Just 1, Just 2, Nothing, Nothing]
 
-  describe "after" $ 
+  describe "after" $
     it "should produce events after a given step" $ do
       let varEv :: Var () (Maybe Int)
           varEv = 1 >>> after 3
           scans = fst $ runIdentity $ scanVar varEv $ replicate 4 ()
       scans `shouldBe` [Nothing, Nothing, Just 3, Just 4]
-  describe "anyE" $ 
+
+  describe "anyE" $
     it "should produce on any event" $ do
       let v1,v2,v3 :: Var () (Maybe Int)
           v1 = use 1 ((1 :: Var () Int) >>> before 2)
@@ -125,8 +118,9 @@
                 return 1
         s3 = do step "e"
                 step "t"
-                return 2 
+                return (2 :: Int)
         s = do x <- raceAny [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"
@@ -206,8 +200,8 @@
         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 :: Float))
-        w = pure 72 `_untilEvent` (use 3 $ 1 >>> after (1 :: Float))
+        v = pure 66 `_untilEvent` use (1-) (1 >>> after (4 :: Float))
+        w = pure 72 `_untilEvent` use 3    (1 >>> after (1 :: Float))
         pduvw = pure (.) <*> u <*> v <*> w
         uvw = u <*> (v <*> w)
     it "(compisition) pure (.) <*> u <*> v <*> w = u <*> (v <*> w)" $
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.7.0.3
+version:             0.7.1.0
 
 -- A short (one-line) description of the package.
 synopsis:            FRP through value streams and monadic splines.
@@ -35,7 +35,7 @@
 
 -- An email address to which users can send suggestions, bug reports, and
 -- patches.
-maintainer:          efsubenovex@gmail.com 
+maintainer:          schell@takt.com
 
 -- A copyright notice.
 -- copyright:
@@ -59,6 +59,9 @@
 
 library
   ghc-options:         -Wall
+  if impl(ghc >= 8)
+    ghc-options:       -Wno-type-defaults
+
   -- Modules exported by the library.
   exposed-modules:     Control.Varying,
                        Control.Varying.Core,
@@ -73,8 +76,9 @@
   -- other-extensions:
 
   -- Other library packages from which modules are imported.
-  build-depends:       base >=4.6 && <5.0
+  build-depends:       base >=4.8 && <5.0
                      , transformers >=0.3
+                     , contravariant >= 1.4
 
   -- Directories containing source files.
   hs-source-dirs:      src
@@ -84,9 +88,11 @@
 
 executable varying-example
   ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
+  if impl(ghc >= 8)
+    ghc-options:       -Wno-type-defaults
 
   -- Other library packages from which modules are imported.
-  build-depends:       base >=4.6 && <5.0
+  build-depends:       base >=4.8 && <5.0
                      , transformers >=0.3
                      , time >=1.4
                      , varying
@@ -103,9 +109,11 @@
 test-suite varying-test
   type:                exitcode-stdio-1.0
   ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
+  if impl(ghc >= 8)
+    ghc-options:       -Wno-type-defaults
 
   -- Other library packages from which modules are imported.
-  build-depends:       base >=4.6 && <5.0
+  build-depends:       base >=4.8 && <5.0
                      , time >=1.4
                      , transformers
                      , varying
@@ -123,9 +131,11 @@
 benchmark varying-bench
   type:                exitcode-stdio-1.0
   ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
+  if impl(ghc >= 8)
+    ghc-options:       -Wno-type-defaults
 
   -- Other library packages from which modules are imported.
-  build-depends:       base >=4.6
+  build-depends:       base >=4.8
                      , time >=1.4
                      , transformers
                      , varying
