diff --git a/Control/Wire.hs b/Control/Wire.hs
--- a/Control/Wire.hs
+++ b/Control/Wire.hs
@@ -1,351 +1,53 @@
 -- |
 -- Module:     Control.Wire
--- Copyright:  (c) 2012 Ertugrul Soeylemez
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
 -- License:    BSD3
 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Netwire is a library for functional reactive programming, that is for
--- time-varying values.  It allows you to express various reactive
--- systems elegantly and concisely by using an embedded domain-specific
--- language.  Examples of such systems include
---
--- * games,
---
--- * network applications with time-varying components,
---
--- * simulations,
---
--- * stateful web applications,
---
--- * widget-based user interfaces.
---
--- This library is based on an extension of the automaton arrow.  The
--- usage is explained in the following tutorial.
 
 module Control.Wire
-    ( -- * Quickstart tutorial
-      -- $quickstart_intro
-
-      -- ** Running wires
-      -- $quickstart_running
-
-      -- ** Constructing wires
-      -- $quickstart_constructing
-
-      -- ** Signal inhibition and events
-      -- $quickstart_inhibition
-
-      -- ** Custom wires
-      -- $quickstart_custom
-
-      -- * Netwire reexports
-      module Control.Wire.Classes,
-      module Control.Wire.Prefab,
+    ( -- * Reexports
+      module Control.Wire.Core,
+      module Control.Wire.Event,
+      module Control.Wire.Interval,
+      module Control.Wire.Run,
       module Control.Wire.Session,
-      module Control.Wire.Trans,
-      module Control.Wire.Types,
-      module Control.Wire.Wire,
+      module Control.Wire.Switch,
+      module Control.Wire.Time,
 
-      -- * Other reexports
+      -- * Convenient type aliases
+      WireP,
+      SimpleWire,
+
+      -- * External
       module Control.Applicative,
       module Control.Arrow,
       module Control.Category,
-      module Data.Proxy,
-      module System.Random,
-      Profunctor(..),
-      Exception(..),
-      SomeException(..)
+      module Data.Semigroup,
+      Identity(..),
+      NominalDiffTime
     )
     where
 
 import Control.Applicative
 import Control.Arrow
 import Control.Category
-import Control.Exception (Exception(..), SomeException(..))
-import Control.Wire.Classes
-import Control.Wire.Prefab
+import Control.Wire.Core
+import Control.Wire.Event
+import Control.Wire.Interval
+import Control.Wire.Run
 import Control.Wire.Session
-import Control.Wire.Trans
-import Control.Wire.Types
-import Control.Wire.Wire hiding (constant, identity, never)
-import Data.Profunctor
-import Data.Proxy (Proxy(..))
-import System.Random
-
-
-{- $quickstart_intro
-
-This section is a quickstart tutorial for the experienced, impatient
-Haskell programmer.
-
-The main concept used in Netwire is a family of /wire categories/:
-
-> data Wire e m a b
-
-A value of type @Wire e m a b@ represents a function that takes as
-arguments
-
-* a time delta of type 'Time' (which is just 'Double') that will be
-  explained below,
-
-* an input value of type @a@.
-
-From these inputs it
-
-* either produces an output value of type @b@ or /inhibits/ with a value
-  of type @e@,
-
-* produces a new wire of type @Wire e m a b@.
-
-So you can think of 'Wire' as:
-
-> newtype Wire e m a b =
->     Wire {
->       stepWire :: Time -> a -> m (Either e b, Wire e m a b)
->     }
-
-To summarize a wire of type @Wire e m a b@ takes a value of type @a@ and
-supposedly produces a value of type @b@.  It can be invoked multiple
-times, where each invocation is called an /instant/ and the wire can
-behave differently at every instant.  Additionally it can choose not to
-produce anything, but instead inhibit with an /inhibition exception/ of
-type @e@.  This is Netwire's notion of a time-varying value.  -}
-
-
-{- $quickstart_running
-
-To actually invoke a wire you can use the 'stepWire' function
-(simplified type):
-
-> stepWire ::
->     (Monad m) =>
->     Wire e m a b ->
->     Time ->
->     a ->
->     m (Either e b, Wire e m a b)
-
-The idea is simple:  You have an application loop that invokes a given
-wire with a time delta, which is just the number of seconds passed since
-the last instant and an application-specific input value.  It then does
-something with the output value (or inhibition value) and restarts the
-loop with the new wire produced by the current wire.  Such an
-application loop based on @stepWire@ could look like this:
-
-> loop w' = do
->     dt <- timeDeltaToLastInstant
->     (mx, w) <- stepWire w' dt ()
->     case mx of
->       Left ex -> printf "Inhibited: %s\n" (show ex)
->       Right x -> printf "Produced: %s\n" (show x)
->     loop w
-
-Usually the time deltas are based on actual clock time.  To simplify
-invocation for this common case there is a set of convenience functions
-like 'stepSession' for stepping that calculate the time deltas for you:
-
-> stepSession ::
->     (Monad m) =>
->     Wire e m a b ->
->     Session m ->
->     a ->
->     m (Either e b, Wire e m a b, Session m)
-
-To construct the initial session value you can use 'clockSession' or one
-of the other predefined intial session values:
-
-> clockSession :: (MonadIO m) => Session m
-
-This simplifies the application loop, because you don't have to
-calculate the time deltas yourself:
-
-> loop w' session' = do
->     (mx, w, session) <- stepSession w' session' ()
->     case mx of
->       Left ex -> printf "Inhibited: %s\n" (show ex)
->       Right x -> printf "Produced: %s\n" (show x)
->     loop w session
-
-For the common case where the wire's underlying monad is 'Identity', but
-the application monad is something else, there are convenience functions
-like 'stepWireP', 'stepSessionP' and other @*P@ variants.
-
-We haven't covered constructing wires yet.  This is explained in the
-next section.  But we now have everything necessary to write our first
-small application:
-
-> module Main where
->
-> import Control.Monad.Identity (Identity)
-> import Control.Wire
-> import Prelude hiding ((.), id)
-> import Text.Printf
->
-> testApp :: Wire () Identity a Time
-> testApp = timeFrom 10
->
-> main :: IO ()
-> main = loop testApp clockSession
->     where
->     loop w' session' = do
->         (mx, w, session) <- stepSessionP w' session' ()
->         case mx of
->           Left ex -> putStrLn ("Inhibited: " ++ show ex)
->           Right x -> putStrLn ("Produced: " ++ show x)
->         loop w session
-
-When you run this program, it will continuously display a number of
-seconds starting with 10.  That's the @timeFrom 10@ wire.  Notice that
-the "Prelude" module is imported with hidden 'Prelude..' and
-'Prelude.id'.  Don't worry, the "Control.Wire" module reexports the
-"Control.Category" module, which includes generalized version of both.
--}
-
-
-{- $quickstart_constructing
-
-A number of convenience types are defined in the "Control.Wire.Types"
-module, in particular the 'WireP' type:
-
-> type WireP = Wire LastException Identity
-
-Wires can be composed categorically, applicatively or by using wire
-combinators.  To feed the output of one wire @w1@ into another wire @w2@
-you just use categorical composition:
-
-> w2 . w1
-
-For example the 'noise' wire generates random noise based on the given
-random number generator.  If its output type is 'Double', it generates
-noise 0 <= x t < 1.  The 'avg' wire calculates the average value of its
-input over the last given number of samples:
-
-> let myNoise = noise (mkStdGen 0) :: WireP a Double
->     myAvg   = avg 1000
-> in myAvg . myNoise
-
-That wire should produce values near 0.5, the average noise value over
-the last 1000 samples of random noise between 0 and 1.  There is a bit
-of cruft here to tell the type system that noise's output type is
-'Double'.  To make this easier you can simply use 'outAs' or 'inAs':
-
-> avg 1000 . outAs pDouble (noise (mkStdGen 0))
-
-The 'Wire' type gives rise to a family of applicative functors.  Using
-applicative style you can apply a function to the output of a wire or
-zip together the outputs of two wires (the "Control.Applicative" module
-is reexported by this module):
-
-> timeString = fmap (printf "%8.2f") time
->
-> noisyTime = liftA2 (+) time (noise (mkStdGen 0))
-
-Constant wires can be produced using 'pure'.  The following wire starts
-at 0 and increases with a constant speed of 3:
-
-> integral_ 0 . pure 3
-
-There are lots of convenience instances for wires.  For example there
-are instances for 'Num', 'Fractional' and 'Data.String.IsString', so you
-can actually just use regular arithmetical operators and numeric
-literals.  If you have enabled the @OverloadedStrings@ extension you can
-also write string literals:
-
-> let n = noise (mkStdGen 0)
-> in time + 3*n
->
-> integral_ 0 . 3
-
-There is a large library of predefined wires below the
-"Control.Wire.Prefab" tree.
--}
+import Control.Wire.Switch
+import Control.Wire.Time
+import Data.Functor.Identity
+import Data.Semigroup
+import Data.Time.Clock
 
 
-{- $quickstart_inhibition
-
-As noted a few times wires can choose not to produce a value.  In those
-cases the wire /inhibits/ the signal.  This is where the @e@ type comes
-into play.  That type is called the /inhibition monoid/.
-
-Signal inhibition is what makes Netwire different.  The 'Wire' type is
-an 'Alternative' functor, where the 'empty' wire always inhibits and
-wires can be combined with the following semantics:
-
-> w1 <|> w2
-
-If @w1@ inhibits, then the combination @w1 \<|\> w2@ acts like @w2@.  In
-other words, the combination chooses the first wire that produces.  If
-both inhibit, then the combination inhibits.
-
-Events are modelled around this.  An event wire is usually a wire that
-acts like the identity wire, but it may inhibit depending on whether an
-event has occurred or not.  One simple event wire is the 'for' wire:
-
-> for 3
-
-This wire acts like the identity wire for three seconds and then stops
-producing forever.  You can use it to construct a wire that produces
-"yes" for three seconds and then switches to "no":
-
-> "yes" . for 3 <|> "no"
-
-Another useful event wire is the 'wackelkontakt' wire (a Netwire running
-gag; it's the German word for slack joint):
-
-> wackelkontakt 0.9
-
-This wire acts like the identity wire most of the time (90%), but
-occasionally inhibits (10%).  Using it you can produce a broken clock,
-which occasionally refuses to display the current time:
-
-> brokenClock =
->     printf "%8.2f" <$> wackelkontakt 0.9 . time <|>
->     "sorry, slack joint"
-
-The 'periodically' wire produces once every given number of seconds.
-The following wire produces once every two seconds:
-
-> periodically 2
-
-There are various combinators for event wires in the
-"Control.Wire.Trans.Event" module, most notably 'hold' and 'holdFor'.
-Given an inhibiting wire the @hold@ combinator holds the last produced
-value, so it turns instantaneous events into continuous ones:
-
-> secondClock = printf "%8.2f" <$> hold (periodically 1 . time)
-
-This one displays the time in seconds and is only updated every second.
-The 'holdFor' combinator allows you to limit the time the last output is
-held for:
-
-> jumpyClock =
->     printf "%8.2f" <$> holdFor 0.5 (periodically 1 . time) <|>
->     "wait 500ms for the next second"
+-- | Pure wires.
 
-You find a library of predefined event wires in the
-"Control.Wire.Prefab.Event" module.
--}
+type WireP s e = Wire s e Identity
 
 
-{- $quickstart_custom
-
-From time to time you will want to write your own wire on a lower level.
-In this case there are a number of options.  The simplest option is
-'mkPure':
-
-> mkPure ::
->     (Time -> a -> (Either e b, Wire e m a b)) ->
->     Wire e m a b
-
-The type quite literally tells what this function does.  It takes a
-function and turns it into a wire quite straightforwardly.  Another
-option is to use 'mkState', which is equivalent to @mkPure@, but allows
-you to express the wire as a local state transformer:
-
-> mkState ::
->     s ->
->     (Time -> (a, s) -> (Either e b, s)) ->
->     Wire e m a b
+-- | Simple wires with time.
 
-The first argument is a starting state, the second is the state
-transformation function.
--}
+type SimpleWire = Wire (Timed NominalDiffTime ()) () Identity
diff --git a/Control/Wire/Classes.hs b/Control/Wire/Classes.hs
deleted file mode 100644
--- a/Control/Wire/Classes.hs
+++ /dev/null
@@ -1,46 +0,0 @@
--- |
--- Module:     Control.Wire.Classes
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Various type classes.
-
-module Control.Wire.Classes
-    ( -- * Effects
-      MonadRandom(..),
-
-      -- * Utility classes
-      Injectable(..)
-    )
-    where
-
-import Data.Monoid
-import System.Random
-
-
--- | Class for injectable values.  See
--- 'Control.Wire.Prefab.Event.inject'.
-
-class Injectable e f where
-    toSignal :: f a -> Either e a
-
-instance (Monoid e) => Injectable e Maybe where
-    toSignal = maybe (Left mempty) Right
-
-instance Injectable e (Either e) where
-    toSignal = id
-
-
--- | Monads with a random number generator.
-
-class (Monad m) => MonadRandom m where
-    -- | Get a random number.
-    getRandom :: (Random a) => m a
-
-    -- | Get a random number in the given range.
-    getRandomR :: (Random a) => (a, a) -> m a
-
-instance MonadRandom IO where
-    getRandom  = randomIO
-    getRandomR = randomRIO
diff --git a/Control/Wire/Core.hs b/Control/Wire/Core.hs
new file mode 100644
--- /dev/null
+++ b/Control/Wire/Core.hs
@@ -0,0 +1,421 @@
+-- |
+-- Module:     Control.Wire.Core
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Control.Wire.Core
+    ( -- * Wires
+      Wire(..),
+      stepWire,
+
+      -- * Constructing wires
+      mkConst,
+      mkEmpty,
+      mkGen,
+      mkGen_,
+      mkGenN,
+      mkId,
+      mkPure,
+      mkPure_,
+      mkPureN,
+      mkSF,
+      mkSF_,
+      mkSFN,
+
+      -- * Data flow and dependencies
+      delay,
+      evalWith,
+      force,
+      forceNF,
+
+      -- * Utilities
+      (&&&!),
+      (***!),
+      lstrict,
+      mapWire
+    )
+    where
+
+import qualified Data.Semigroup as Sg
+import Control.Applicative
+import Control.Arrow
+import Control.Category
+import Control.DeepSeq hiding (force)
+import Control.Monad
+import Control.Monad.Fix
+import Control.Parallel.Strategies
+import Data.Monoid
+import Data.String
+import Prelude hiding ((.), id)
+
+
+-- | A wire is a signal function.  It maps a reactive value to another
+-- reactive value.
+
+data Wire s e m a b where
+    WArr   :: (Either e a -> Either e b) -> Wire s e m a b
+    WConst :: Either e b -> Wire s e m a b
+    WGen   :: (s -> Either e a -> m (Either e b, Wire s e m a b)) -> Wire s e m a b
+    WId    :: Wire s e m a a
+    WPure  :: (s -> Either e a -> (Either e b, Wire s e m a b)) -> Wire s e m a b
+
+instance (Monad m, Monoid e) => Alternative (Wire s e m a) where
+    empty = WConst (Left mempty)
+
+    w1' <|> w2' =
+        WGen $ \ds mx' ->
+            liftM2 (\(mx1, w1) (mx2, w2) -> lstrict (choose mx1 mx2, w1 <|> w2))
+                   (stepWire w1' ds mx')
+                   (stepWire w2' ds mx')
+
+        where
+        choose mx1@(Right _) _       = mx1
+        choose _ mx2@(Right _)       = mx2
+        choose (Left ex1) (Left ex2) = Left (ex1 <> ex2)
+
+instance (Monad m) => Applicative (Wire s e m a) where
+    pure = WConst . Right
+
+    wf' <*> wx' =
+        WGen $ \ds mx' ->
+            liftM2 (\(mf, wf) (mx, wx) -> lstrict (mf <*> mx, wf <*> wx))
+                   (stepWire wf' ds mx')
+                   (stepWire wx' ds mx')
+
+instance (Monad m) => Arrow (Wire s e m) where
+    arr f = WArr (fmap f)
+
+    first w' =
+        WGen $ \ds mxy' ->
+            liftM (\(mx, w) -> lstrict (liftA2 (,) mx (fmap snd mxy'), first w))
+                  (stepWire w' ds (fmap fst mxy'))
+
+instance (Monad m, Monoid e) => ArrowChoice (Wire s e m) where
+    left w' =
+        WGen $ \ds mmx' ->
+            liftM (fmap Left ***! left) .
+            stepWire w' ds $
+            case mmx' of
+              Right (Left x)  -> Right x
+              Right (Right _) -> Left mempty
+              Left ex         -> Left ex
+
+    right w' =
+        WGen $ \ds mmx' ->
+            liftM (fmap Right ***! right) .
+            stepWire w' ds $
+            case mmx' of
+              Right (Right x)  -> Right x
+              Right (Left _)   -> Left mempty
+              Left ex          -> Left ex
+
+    wl' +++ wr' =
+        WGen $ \ds mmx' ->
+            case mmx' of
+              Right (Left x) -> do
+                  liftM2 (\(mx, wl) (_, wr) -> lstrict (fmap Left mx, wl +++ wr))
+                         (stepWire wl' ds (Right x))
+                         (stepWire wr' ds (Left mempty))
+              Right (Right x) -> do
+                  liftM2 (\(_, wl) (mx, wr) -> lstrict (fmap Right mx, wl +++ wr))
+                         (stepWire wl' ds (Left mempty))
+                         (stepWire wr' ds (Right x))
+              Left ex ->
+                  liftM2 (\(_, wl) (_, wr) -> lstrict (Left ex, wl +++ wr))
+                         (stepWire wl' ds (Left ex))
+                         (stepWire wr' ds (Left ex))
+
+    wl' ||| wr' =
+        WGen $ \ds mmx' ->
+            case mmx' of
+              Right (Left x) -> do
+                  liftM2 (\(mx, wl) (_, wr) -> lstrict (mx, wl ||| wr))
+                         (stepWire wl' ds (Right x))
+                         (stepWire wr' ds (Left mempty))
+              Right (Right x) -> do
+                  liftM2 (\(_, wl) (mx, wr) -> lstrict (mx, wl ||| wr))
+                         (stepWire wl' ds (Left mempty))
+                         (stepWire wr' ds (Right x))
+              Left ex ->
+                  liftM2 (\(_, wl) (_, wr) -> lstrict (Left ex, wl ||| wr))
+                         (stepWire wl' ds (Left ex))
+                         (stepWire wr' ds (Left ex))
+
+instance (MonadFix m) => ArrowLoop (Wire s e m) where
+    loop w' =
+        WGen $ \ds mx' ->
+            liftM (fmap fst ***! loop) .
+            mfix $ \ ~(mx, _) ->
+                let d | Right (_, d) <- mx = d
+                      | otherwise = error "Feedback broken by inhibition"
+                in stepWire w' ds (fmap (, d) mx')
+
+instance (Monad m, Monoid e) => ArrowPlus (Wire s e m) where
+    (<+>) = (<|>)
+
+instance (Monad m, Monoid e) => ArrowZero (Wire s e m) where
+    zeroArrow = empty
+
+instance (Monad m) => Category (Wire s e m) where
+    id = WId
+
+    w2' . w1' =
+        WGen $ \ds mx0 -> do
+            (mx1, w1) <- stepWire w1' ds mx0
+            (mx2, w2) <- stepWire w2' ds mx1
+            mx2 `seq` return (mx2, w2 . w1)
+
+instance (Monad m, Floating b) => Floating (Wire s e m a b) where
+    (**) = liftA2 (**)
+    acos = fmap acos
+    acosh = fmap acosh
+    asin = fmap asin
+    asinh = fmap asinh
+    atan = fmap atan
+    atanh = fmap atanh
+    cos = fmap cos
+    cosh = fmap cosh
+    exp = fmap exp
+    log = fmap log
+    logBase = liftA2 logBase
+    pi = pure pi
+    sin = fmap sin
+    sinh = fmap sinh
+    sqrt = fmap sqrt
+    tan = fmap tan
+    tanh = fmap tanh
+
+instance (Monad m, Fractional b) => Fractional (Wire s e m a b) where
+    (/)   = liftA2 (/)
+    recip = fmap recip
+    fromRational = pure . fromRational
+
+instance (Monad m) => Functor (Wire s e m a) where
+    fmap f (WArr g)    = WArr (fmap f . g)
+    fmap f (WConst mx) = WConst (fmap f mx)
+    fmap f (WGen g)    = WGen (\ds -> liftM (fmap f ***! fmap f) . g ds)
+    fmap f WId         = WArr (fmap f)
+    fmap f (WPure g)   = WPure (\ds -> (fmap f ***! fmap f) . g ds)
+
+instance (Monad m, IsString b) => IsString (Wire s e m a b) where
+    fromString = pure . fromString
+
+instance (Monad m, Monoid b) => Monoid (Wire s e m a b) where
+    mempty = pure mempty
+    mappend = liftA2 mappend
+
+instance (Monad m, Num b) => Num (Wire s e m a b) where
+    (+) = liftA2 (+)
+    (-) = liftA2 (-)
+    (*) = liftA2 (*)
+    abs    = fmap abs
+    negate = fmap negate
+    signum = fmap signum
+    fromInteger = pure . fromInteger
+
+instance (Monad m, Sg.Semigroup b) => Sg.Semigroup (Wire s e m a b) where
+    (<>) = liftA2 (Sg.<>)
+
+
+-- | Left-strict version of '&&&' for functions.
+
+(&&&!) :: (a -> b) -> (a -> c) -> (a -> (b, c))
+(&&&!) f g x' =
+    let (x, y) = (f x', g x')
+    in x `seq` (x, y)
+
+
+-- | Left-strict version of '***' for functions.
+
+(***!) :: (a -> c) -> (b -> d) -> ((a, b) -> (c, d))
+(***!) f g (x', y') =
+    let (x, y) = (f x', g y')
+    in x `seq` (x, y)
+
+
+-- | This wire delays its input signal by the smallest possible
+-- (semantically infinitesimal) amount of time.  You can use it when you
+-- want to use feedback ('ArrowLoop'):  If the user of the feedback
+-- depends on /now/, delay the value before feeding it back.  The
+-- argument value is the replacement signal at the beginning.
+--
+-- * Depends: before now.
+
+delay :: a -> Wire s e m a a
+delay x' = mkSFN $ \x -> (x', delay x)
+
+
+-- | Evaluate the input signal using the given 'Strategy' here.  This
+-- wire evaluates only produced values.
+--
+-- * Depends: now.
+
+evalWith :: Strategy a -> Wire s e m a a
+evalWith s =
+    WArr $ \mx ->
+        case mx of
+          Right x -> (x `using` s) `seq` mx
+          Left _  -> mx
+
+
+-- | Force the input signal to WHNF here.  This wire forces both
+-- produced values and inhibition values.
+--
+-- * Depends: now.
+
+force :: Wire s e m a a
+force =
+    WArr $ \mx ->
+        case mx of
+          Right x -> x `seq` mx
+          Left ex -> ex `seq` mx
+
+
+-- | Force the input signal to NF here.  This wire forces only produced
+-- values.
+--
+-- * Depends: now.
+
+forceNF :: (NFData a) => Wire s e m a a
+forceNF =
+    WArr $ \mx ->
+        case mx of
+          Right x -> x `deepseq` mx
+          Left _  -> mx
+
+
+-- | Left-strict tuple.
+
+lstrict :: (a, b) -> (a, b)
+lstrict (x, y) = x `seq` (x, y)
+
+
+-- | Apply the given monad morphism to the wire's underlying monad.
+
+mapWire ::
+    (Monad m', Monad m)
+    => (forall a. m' a -> m a)
+    -> Wire s e m' a b
+    -> Wire s e m a b
+mapWire _ (WArr g)    = WArr g
+mapWire _ (WConst mx) = WConst mx
+mapWire f (WGen g)    = WGen (\ds -> liftM (lstrict . second (mapWire f)) . f . g ds)
+mapWire _ WId         = WId
+mapWire f (WPure g)   = WPure (\ds -> lstrict . second (mapWire f) . g ds)
+
+
+-- | Construct a stateless wire from the given signal mapping function.
+
+mkConst :: Either e b -> Wire s e m a b
+mkConst = WConst
+
+
+-- | Construct the empty wire, which inhibits forever.
+
+mkEmpty :: (Monoid e) => Wire s e m a b
+mkEmpty = mkConst (Left mempty)
+
+
+-- | Construct a stateful wire from the given transition function.
+
+mkGen :: (Monad m, Monoid s) => (s -> a -> m (Either e b, Wire s e m a b)) -> Wire s e m a b
+mkGen f = loop mempty
+    where
+    loop s' =
+        WGen $ \ds mx ->
+            let s = s' <> ds in
+            s `seq`
+            case mx of
+              Left ex  -> return (Left ex, loop s)
+              Right x' -> liftM lstrict (f s x')
+
+
+-- | Construct a stateless wire from the given transition function.
+
+mkGen_ :: (Monad m) => (a -> m (Either e b)) -> Wire s e m a b
+mkGen_ f = loop
+    where
+    loop =
+        WGen $ \_ mx ->
+            case mx of
+              Left ex -> return (Left ex, loop)
+              Right x -> liftM (lstrict . (, loop)) (f x)
+
+
+-- | Construct a stateful wire from the given transition function.
+
+mkGenN :: (Monad m) => (a -> m (Either e b, Wire s e m a b)) -> Wire s e m a b
+mkGenN f = loop
+    where
+    loop =
+        WGen $ \_ mx ->
+            case mx of
+              Left ex  -> return (Left ex, loop)
+              Right x' -> liftM lstrict (f x')
+
+
+-- | Construct the identity wire.
+
+mkId :: Wire s e m a a
+mkId = WId
+
+
+-- | Construct a pure stateful wire from the given transition function.
+
+mkPure :: (Monoid s) => (s -> a -> (Either e b, Wire s e m a b)) -> Wire s e m a b
+mkPure f = loop mempty
+    where
+    loop s' =
+        WPure $ \ds mx ->
+            let s = s' <> ds in
+            s `seq`
+            case mx of
+              Left ex  -> (Left ex, loop s)
+              Right x' -> lstrict (f s x')
+
+
+-- | Construct a pure stateless wire from the given transition function.
+
+mkPure_ :: (a -> Either e b) -> Wire s e m a b
+mkPure_ f = WArr $ (>>= f)
+
+
+-- | Construct a pure stateful wire from the given transition function.
+
+mkPureN :: (a -> (Either e b, Wire s e m a b)) -> Wire s e m a b
+mkPureN f = loop
+    where
+    loop =
+        WPure $ \_ mx ->
+            case mx of
+              Left ex  -> (Left ex, loop)
+              Right x' -> lstrict (f x')
+
+
+-- | Construct a pure stateful wire from the given signal function.
+
+mkSF :: (Monoid s) => (s -> a -> (b, Wire s e m a b)) -> Wire s e m a b
+mkSF f = mkPure (\ds -> lstrict . first (Right) . f ds)
+
+
+-- | Construct a pure stateless wire from the given function.
+
+mkSF_ :: (a -> b) -> Wire s e m a b
+mkSF_ f = WArr (fmap f)
+
+
+-- | Construct a pure stateful wire from the given signal function.
+
+mkSFN :: (a -> (b, Wire s e m a b)) -> Wire s e m a b
+mkSFN f = mkPureN (lstrict . first (Right) . f)
+
+
+-- | Perform one step of the given wire.
+
+stepWire :: (Monad m) => Wire s e m a b -> s -> Either e a -> m (Either e b, Wire s e m a b)
+stepWire w@(WArr f)    _  mx' = return (f mx', w)
+stepWire w@(WConst mx) _  mx' = return (mx' *> mx, w)
+stepWire (WGen f)      ds mx' = f ds mx'
+stepWire w@WId         _  mx' = return (mx', w)
+stepWire (WPure f)     ds mx' = return (f ds mx')
diff --git a/Control/Wire/Event.hs b/Control/Wire/Event.hs
new file mode 100644
--- /dev/null
+++ b/Control/Wire/Event.hs
@@ -0,0 +1,338 @@
+-- |
+-- Module:     Control.Wire.Event
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Control.Wire.Event
+    ( -- * Events
+      Event,
+
+      -- * Time-based
+      at,
+      never,
+      now,
+      periodic,
+      periodicList,
+
+      -- * Signal analysis
+      became,
+      noLonger,
+
+      -- * Modifiers
+      (<&),
+      (&>),
+      dropE,
+      dropWhileE,
+      filterE,
+      merge,
+      mergeL,
+      mergeR,
+      notYet,
+      once,
+      takeE,
+      takeWhileE,
+
+      -- * Scans
+      accumE,
+      accum1E,
+      iterateE,
+      -- ** Special scans
+      maximumE,
+      minimumE,
+      productE,
+      sumE
+    )
+    where
+
+import Control.Applicative
+import Control.Arrow
+import Control.Monad.Fix
+import Control.Wire.Core
+import Control.Wire.Session
+import Control.Wire.Unsafe.Event
+import Data.Fixed
+
+
+-- | Merge events with the leftmost event taking precedence.  Equivalent
+-- to using the monoid interface with 'First'.  Infixl 5.
+--
+-- * Depends: now on both.
+--
+-- * Inhibits: when any of the two wires inhibit.
+
+(<&) :: (Monad m) => Wire s e m a (Event b) -> Wire s e m a (Event b) -> Wire s e m a (Event b)
+(<&) = liftA2 (merge const)
+
+infixl 5 <&
+
+
+-- | Merge events with the rightmost event taking precedence.
+-- Equivalent to using the monoid interface with 'Last'.  Infixl 5.
+--
+-- * Depends: now on both.
+--
+-- * Inhibits: when any of the two wires inhibit.
+
+(&>) :: (Monad m) => Wire s e m a (Event b) -> Wire s e m a (Event b) -> Wire s e m a (Event b)
+(&>) = liftA2 (merge (const id))
+
+infixl 5 &>
+
+
+-- | Left scan for events.  Each time an event occurs, apply the given
+-- function.
+--
+-- * Depends: now.
+
+accumE ::
+    (b -> a -> b)  -- ^ Fold function
+    -> b           -- ^ Initial value.
+    -> Wire s e m (Event a) (Event b)
+accumE f = loop
+    where
+    loop x' =
+        mkSFN $
+            event (NoEvent, loop x')
+                  (\y -> let x = f x' y in (Event x, loop x))
+
+
+-- | Left scan for events with no initial value.  Each time an event
+-- occurs, apply the given function.  The first event is produced
+-- unchanged.
+--
+-- * Depends: now.
+
+accum1E ::
+    (a -> a -> a)  -- ^ Fold function
+    -> Wire s e m (Event a) (Event a)
+accum1E f = initial
+    where
+    initial =
+        mkSFN $ event (NoEvent, initial) (Event &&& accumE f)
+
+
+-- | At the given point in time.
+--
+-- * Depends: now when occurring.
+
+at ::
+    (HasTime t s)
+    => t  -- ^ Time of occurrence.
+    -> Wire s e m a (Event a)
+at t' =
+    mkSF $ \ds x ->
+        let t = t' - dtime ds
+        in if t <= 0
+             then (Event x, never)
+             else (NoEvent, at t)
+
+
+-- | Occurs each time the predicate becomes true for the input signal,
+-- for example each time a given threshold is reached.
+--
+-- * Depends: now.
+
+became :: (a -> Bool) -> Wire s e m a (Event a)
+became p = off
+    where
+    off = mkSFN $ \x -> if p x then (Event x, on) else (NoEvent, off)
+    on = mkSFN $ \x -> (NoEvent, if p x then on else off)
+
+
+-- | Forget the first given number of occurrences.
+--
+-- * Depends: now.
+
+dropE :: Int -> Wire s e m (Event a) (Event a)
+dropE n | n <= 0 = mkId
+dropE n =
+    fix $ \again ->
+    mkSFN $ \mev ->
+        (NoEvent, if occurred mev then dropE (pred n) else again)
+
+
+-- | Forget all initial occurrences until the given predicate becomes
+-- false.
+--
+-- * Depends: now.
+
+dropWhileE :: (a -> Bool) -> Wire s e m (Event a) (Event a)
+dropWhileE p =
+    fix $ \again ->
+    mkSFN $ \mev ->
+        case mev of
+          Event x | not (p x) -> (mev, mkId)
+          _ -> (NoEvent, again)
+
+
+-- | Forget all occurrences for which the given predicate is false.
+--
+-- * Depends: now.
+
+filterE :: (a -> Bool) -> Wire s e m (Event a) (Event a)
+filterE p =
+    mkSF_ $ \mev ->
+        case mev of
+          Event x | p x -> mev
+          _ -> NoEvent
+
+
+-- | On each occurrence, apply the function the event carries.
+--
+-- * Depends: now.
+
+iterateE :: a -> Wire s e m (Event (a -> a)) (Event a)
+iterateE = accumE (\x f -> f x)
+
+
+-- | Maximum of all events.
+--
+-- * Depends: now.
+
+maximumE :: (Ord a) => Wire s e m (Event a) (Event a)
+maximumE = accum1E max
+
+
+-- | Minimum of all events.
+--
+-- * Depends: now.
+
+minimumE :: (Ord a) => Wire s e m (Event a) (Event a)
+minimumE = accum1E min
+
+
+-- | Left-biased event merge.
+
+mergeL :: Event a -> Event a -> Event a
+mergeL = merge const
+
+
+-- | Right-biased event merge.
+
+mergeR :: Event a -> Event a -> Event a
+mergeR = merge (const id)
+
+
+-- | Never occurs.
+
+never :: Wire s e m a (Event b)
+never = mkConst (Right NoEvent)
+
+
+-- | Occurs each time the predicate becomes false for the input signal,
+-- for example each time a given threshold is no longer exceeded.
+--
+-- * Depends: now.
+
+noLonger :: (a -> Bool) -> Wire s e m a (Event a)
+noLonger p = off
+    where
+    off = mkSFN $ \x -> if p x then (NoEvent, off) else (Event x, on)
+    on = mkSFN $ \x -> (NoEvent, if p x then off else on)
+
+
+-- | Forget the first occurrence.
+--
+-- * Depends: now.
+
+notYet :: Wire s e m (Event a) (Event a)
+notYet =
+    mkSFN $ event (NoEvent, notYet) (const (NoEvent, mkId))
+
+
+-- | Occurs once immediately.
+--
+-- * Depends: now when occurring.
+
+now :: Wire s e m a (Event a)
+now = mkSFN $ \x -> (Event x, never)
+
+
+-- | Forget all occurrences except the first.
+--
+-- * Depends: now when occurring.
+
+once :: Wire s e m (Event a) (Event a)
+once =
+    mkSFN $ \mev ->
+        (mev, if occurred mev then never else once)
+
+
+-- | Periodic occurrence with the given time period.  First occurrence
+-- is now.
+--
+-- * Depends: now when occurring.
+
+periodic :: (HasTime t s) => t -> Wire s e m a (Event a)
+periodic int | int <= 0 = error "periodic: Non-positive interval"
+periodic int = mkSFN $ \x -> (Event x, loop int)
+    where
+    loop 0 = loop int
+    loop t' =
+        mkSF $ \ds x ->
+            let t = t' - dtime ds
+            in if t <= 0
+                 then (Event x, loop (mod' t int))
+                 else (NoEvent, loop t)
+
+
+-- | Periodic occurrence with the given time period.  First occurrence
+-- is now.  The event values are picked one by one from the given list.
+-- When the list is exhausted, the event does not occur again.
+
+periodicList :: (HasTime t s) => t -> [b] -> Wire s e m a (Event b)
+periodicList int _ | int <= 0 = error "periodic: Non-positive interval"
+periodicList _ [] = never
+periodicList int (x:xs) = mkSFN $ \_ -> (Event x, loop int xs)
+    where
+    loop _ [] = never
+    loop 0 xs = loop int xs
+    loop t' xs0@(x:xs) =
+        mkSF $ \ds _ ->
+            let t = t' - dtime ds
+            in if t <= 0
+                 then (Event x, loop (mod' t int) xs)
+                 else (NoEvent, loop t xs0)
+
+
+-- | Product of all events.
+--
+-- * Depends: now.
+
+productE :: (Num a) => Wire s e m (Event a) (Event a)
+productE = accumE (*) 1
+
+
+-- | Sum of all events.
+--
+-- * Depends: now.
+
+sumE :: (Num a) => Wire s e m (Event a) (Event a)
+sumE = accumE (+) 0
+
+
+-- | Forget all but the first given number of occurrences.
+--
+-- * Depends: now.
+
+takeE :: Int -> Wire s e m (Event a) (Event a)
+takeE n | n <= 0 = never
+takeE n =
+    fix $ \again ->
+    mkSFN $ \mev ->
+        (mev, if occurred mev then takeE (pred n) else again)
+
+
+-- | Forget all but the initial occurrences for which the given
+-- predicate is true.
+--
+-- * Depends: now.
+
+takeWhileE :: (a -> Bool) -> Wire s e m (Event a) (Event a)
+takeWhileE p =
+    fix $ \again ->
+    mkSFN $ \mev ->
+        case mev of
+          Event x | not (p x) -> (NoEvent, never)
+          _ -> (mev, again)
diff --git a/Control/Wire/Interval.hs b/Control/Wire/Interval.hs
new file mode 100644
--- /dev/null
+++ b/Control/Wire/Interval.hs
@@ -0,0 +1,184 @@
+-- |
+-- Module:     Control.Wire.Interval
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Control.Wire.Interval
+    ( -- * Basic intervals
+      inhibit,
+
+      -- * Time intervals
+      after,
+      for,
+
+      -- * Signal analysis
+      unless,
+      when,
+
+      -- * Event-based intervals
+      asSoonAs,
+      between,
+      hold,
+      holdFor,
+      until
+    )
+    where
+
+import Control.Arrow
+import Control.Wire.Core
+import Control.Wire.Event
+import Control.Wire.Session
+import Control.Wire.Unsafe.Event
+import Data.Monoid
+import Prelude hiding (until)
+
+
+-- | After the given time period.
+--
+-- * Depends: now after the given time period.
+--
+-- * Inhibits: for the given time period.
+
+after :: (HasTime t s, Monoid e) => t -> Wire s e m a a
+after t' =
+    mkPure $ \ds x ->
+        let t = t' - dtime ds in
+        if t <= 0
+          then (Right x, mkId)
+          else (Left mempty, after t)
+
+
+-- | Alias for 'hold'.
+
+asSoonAs :: (Monoid e) => Wire s e m (Event a) a
+asSoonAs = hold
+
+
+-- | Start each time the left event occurs, stop each time the right
+-- event occurs.
+--
+-- * Depends: now when active.
+--
+-- * Inhibits: after the right event occurred, before the left event
+-- occurs.
+
+between :: (Monoid e) => Wire s e m (a, Event b, Event c) a
+between =
+    mkPureN $ \(x, onEv, _) ->
+        event (Left mempty, between)
+              (const (Right x, active))
+              onEv
+
+    where
+    active =
+        mkPureN $ \(x, _, offEv) ->
+            event (Right x, active)
+                  (const (Left mempty, between))
+                  offEv
+
+
+-- | For the given time period.
+--
+-- * Depends: now for the given time period.
+--
+-- * Inhibits: after the given time period.
+
+for :: (HasTime t s, Monoid e) => t -> Wire s e m a a
+for t' =
+    mkPure $ \ds x ->
+        let t = t' - dtime ds in
+        if t <= 0
+          then (Left mempty, mkEmpty)
+          else (Right x, for t)
+
+
+-- | Start when the event occurs for the first time reflecting its
+-- latest value.
+--
+-- * Depends: now.
+--
+-- * Inhibits: until the event occurs for the first time.
+
+hold :: (Monoid e) => Wire s e m (Event a) a
+hold =
+    mkPureN $
+        event (Left mempty, hold)
+              (Right &&& holdWith)
+
+    where
+    holdWith x =
+        mkPureN $
+            event (Right x, holdWith x)
+                  (Right &&& holdWith)
+
+
+-- | Hold each event occurrence for the given time period.  Inhibits
+-- when no event occurred for the given amount of time.  New occurrences
+-- override old occurrences, even when they are still held.
+--
+-- * Depends: now.
+--
+-- * Inhibits: when no event occurred for the given amount of time.
+
+holdFor :: (HasTime t s, Monoid e) => t -> Wire s e m (Event a) a
+holdFor int | int <= 0 = error "holdFor: Non-positive interval."
+holdFor int = off
+    where
+    off =
+        mkPure $ \_ ->
+            event (Left mempty, off)
+                  (Right &&& on int)
+
+    on t' x' =
+        mkPure $ \ds ->
+            let t = t' - dtime ds in
+            event (if t <= 0
+                     then (Left mempty, off)
+                     else (Right x', on t x'))
+                  (Right &&& on int)
+
+
+-- | Inhibit forever with the given value.
+--
+-- * Inhibits: always.
+
+inhibit :: e -> Wire s e m a b
+inhibit = mkConst . Left
+
+
+-- | When the given predicate is false for the input signal.
+--
+-- * Depends: now.
+--
+-- * Inhibits: unless the predicate is false.
+
+unless :: (Monoid e) => (a -> Bool) -> Wire s e m a a
+unless p =
+    mkPure_ $ \x ->
+        if p x then Left mempty else Right x
+
+
+-- | Produce until the given event occurs.  When it occurs, inhibit with
+-- its value forever.
+--
+-- * Depends: now until event occurs.
+--
+-- * Inhibits: forever after event occurs.
+
+until :: (Monoid e) => Wire s e m (a, Event b) a
+until =
+    mkPureN . uncurry $ \x ->
+        event (Right x, until) (const (Left mempty, mkEmpty))
+
+
+-- | When the given predicate is true for the input signal.
+--
+-- * Depends: now.
+--
+-- * Inhibits: when the predicate is false.
+
+when :: (Monoid e) => (a -> Bool) -> Wire s e m a a
+when p =
+    mkPure_ $ \x ->
+        if p x then Right x else Left mempty
diff --git a/Control/Wire/Prefab.hs b/Control/Wire/Prefab.hs
deleted file mode 100644
--- a/Control/Wire/Prefab.hs
+++ /dev/null
@@ -1,35 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Proxy module for the prefab wires.
-
-module Control.Wire.Prefab
-    ( -- * Reexports
-      module Control.Wire.Prefab.Accum,
-      module Control.Wire.Prefab.Analyze,
-      module Control.Wire.Prefab.Effect,
-      module Control.Wire.Prefab.Event,
-      module Control.Wire.Prefab.List,
-      module Control.Wire.Prefab.Move,
-      module Control.Wire.Prefab.Noise,
-      module Control.Wire.Prefab.Queue,
-      module Control.Wire.Prefab.Sample,
-      module Control.Wire.Prefab.Simple,
-      module Control.Wire.Prefab.Time
-    )
-    where
-
-import Control.Wire.Prefab.Accum
-import Control.Wire.Prefab.Analyze
-import Control.Wire.Prefab.Effect
-import Control.Wire.Prefab.Event
-import Control.Wire.Prefab.List
-import Control.Wire.Prefab.Move
-import Control.Wire.Prefab.Noise
-import Control.Wire.Prefab.Queue
-import Control.Wire.Prefab.Sample
-import Control.Wire.Prefab.Simple
-import Control.Wire.Prefab.Time
diff --git a/Control/Wire/Prefab/Accum.hs b/Control/Wire/Prefab/Accum.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Accum.hs
+++ /dev/null
@@ -1,132 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Accum
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Accumulation wires.  These are left-scan equivalents of several
--- sorts.
-
-module Control.Wire.Prefab.Accum
-    ( -- * General
-      -- ** Accumulation
-      accum,
-      accumT,
-      accum1,
-      accumT1,
-      -- ** Function iteration
-      iterateW,
-      iterateWT,
-      -- ** Generic unfolding
-      unfold,
-      unfoldT,
-
-       -- * Special
-      countFrom,
-      enumFromW,
-      mconcatW
-    )
-    where
-
-import Control.Wire.Wire
-import Data.AdditiveGroup
-import Data.Monoid
-import Prelude hiding (enumFrom, iterate)
-
-
--- | The most general accumulator.  This wire corresponds to a left
--- scan.
---
--- * Depends: previous instant.
-
-accum :: (b -> a -> b) -> b -> Wire e m a b
-accum f = accumT (const f)
-
-
--- | Non-delaying variant of 'accum'.
---
--- * Depends: current instant.
-
-accum1 :: (b -> a -> b) -> b -> Wire e m a b
-accum1 f = accumT1 (const f)
-
-
--- | Like 'accum', but the accumulation function also receives the
--- current time delta.
---
--- * Depends: previous instant.
-
-accumT :: (Time -> b -> a -> b) -> b -> Wire e m a b
-accumT f x' =
-    mkPure $ \dt x ->
-        x' `seq` (Right x', accumT f (f dt x' x))
-
-
--- | Non-delaying variant of 'accumT'.
---
--- * Depends: current instant.
-
-accumT1 :: (Time -> b -> a -> b) -> b -> Wire e m a b
-accumT1 f x' =
-    mkPure $ \dt x ->
-        let y = f dt x' x in
-        x' `seq` (Right y, accumT1 f y)
-
-
--- | Counts from the given vector adding the current input for the next
--- instant.
---
--- * Depends: previous instant.
-
-countFrom :: (AdditiveGroup b) => b -> Wire e m b b
-countFrom = accum (^+^)
-
-
--- | Enumerates from the given element.
-
-enumFromW :: (Enum b) => b -> Wire e m a b
-enumFromW = accum (\x _ -> succ x)
-
-
--- | Apply the input function continously.  Corresponds to 'iterate' for
--- lists.
-
-iterateW :: (b -> b) -> b -> Wire e m a b
-iterateW f = accum (\x _ -> f x)
-
-
--- | Like 'iterate', but the accumulation function also receives the
--- current time delta.
-
-iterateWT :: (Time -> b -> b) -> b -> Wire e m a b
-iterateWT f = accumT (\dt x _ -> f dt x)
-
-
--- | Running 'Monoid' sum.
---
--- * Depends: previous instant.
-
-mconcatW :: (Monoid b) => Wire e m b b
-mconcatW = accum mappend mempty
-
-
--- | Corresponds to 'unfoldr' for lists.
---
--- * Depends: current instant, if the unfolding function is strict in
--- its second argument.
-
-unfold :: (s -> a -> (b, s)) -> s -> Wire e m a b
-unfold = unfoldT . const
-
-
--- | Like 'unfold', but the accumulation function also receives the
--- current time delta.
---
--- * Depends: current instant, if the given function is strict in its
--- third argument.
-
-unfoldT :: (Time -> s -> a -> (b, s)) -> s -> Wire e m a b
-unfoldT f s' =
-    mkPure $ \dt x' ->
-        let (x, s) = f dt s' x' in
-        s' `seq` (Right x, unfoldT f s)
diff --git a/Control/Wire/Prefab/Analyze.hs b/Control/Wire/Prefab/Analyze.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Analyze.hs
+++ /dev/null
@@ -1,243 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Analyze
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Signal analysis wires.
-
-module Control.Wire.Prefab.Analyze
-    ( -- * Statistics
-      -- ** Average
-      avg,
-      avgInt,
-      avgAll,
-      avgFps,
-      avgFpsInt,
-      -- ** Peak
-      highPeak,
-      lowPeak,
-      peakBy,
-
-      -- * Monitoring
-      collect,
-      firstSeen,
-      lastSeen
-    )
-    where
-
-import qualified Data.Map as M
-import qualified Data.Sequence as Seq
-import Control.Category
-import Control.Wire.Prefab.Time
-import Control.Wire.Wire
-import Data.Map (Map)
-import Data.Monoid
-import Data.Sequence (Seq, ViewL(..), (|>), viewl)
-import Data.VectorSpace
-import Prelude hiding ((.), id)
-
-
--- | Calculate the average of the signal over the given number of last
--- samples.  If you need an average over all samples ever produced,
--- consider using 'avgAll' instead.
---
--- * Complexity: O(n) space wrt number of samples.
---
--- * Depends: current instant.
-
-avg ::
-    forall a m e v.
-    (Fractional a, VectorSpace v, Scalar v ~ a)
-    => Int
-    -> Wire e m v v
-avg n | n <= 0 = error "avg: The number of samples must be positive"
-avg n =
-    mkPure $ \_ x ->
-        (Right x, avg' (Seq.replicate n (x ^/ d)) x)
-
-    where
-    avg' :: Seq v -> v -> Wire e m v v
-    avg' samples'' a' =
-        mkPure $ \_ x ->
-            let xa              = x ^/ d
-                xa' :< samples' = viewl samples''
-                samples         = samples' |> xa
-                a               = a' ^-^ xa' ^+^ xa
-            in a `seq` (Right a, avg' samples a)
-
-    d :: Scalar v
-    d = realToFrac n
-
-
--- | Calculate the average of the input signal over all samples.  This
--- is usually not what you want.  In most cases the 'avg' wire is
--- preferable.
---
--- * Depends: current instant.
-
-avgAll ::
-    forall a m e v.
-    (Fractional a, VectorSpace v, Scalar v ~ a)
-    => Wire e m v v
-avgAll = mkPure $ \_ x -> (Right x, avgAll' 1 x)
-    where
-    avgAll' :: a -> v -> Wire e m v v
-    avgAll' n' a' =
-        mkPure $ \_ x ->
-            let n = n' + 1
-                a = a' ^+^ (x ^-^ a') ^/ n
-            in a' `seq` (Right a, avgAll' n a)
-
-
--- | Calculate the average number of instants per second for the last
--- given number of instants.  In a continuous game or simulation this
--- corresponds to the average number of frames per second, hence the
--- name.
---
--- * Complexity:  O(n) space wrt number of samples.
---
--- * Depends: time.
-
-avgFps :: (Monad m) => Int -> Wire e m a Double
-avgFps n = recip (avg n) . dtime
-
-
--- | Like 'avgFps', but sample in discrete intervals only.  This can
--- greatly enhance the performance, when you have an inefficient clock
--- source.
---
--- * Complexity:  O(n) space wrt number of samples.
---
--- * Depends: time.
-
-avgFpsInt ::
-    (Monad m)
-    => Int  -- ^ Sampling interval.
-    -> Int  -- ^ Number of samples.
-    -> Wire e m a Double
-avgFpsInt int n = recip (avgInt int n) . dtime
-
-
--- | Same as 'avg', but with a sampling interval.  This can be used to
--- increase the performance, if the input is complicated.
---
--- * Complexity: O(n) space wrt number of samples.
---
--- * Depends: current instant.
-
-avgInt ::
-    forall a m e v.
-    (Fractional a, VectorSpace v, Scalar v ~ a)
-    => Int  -- ^ Sampling interval.
-    -> Int  -- ^ Number of samples.
-    -> Wire e m v v
-avgInt _ n | n <= 0 = error "avg: The number of samples must be positive"
-avgInt int n =
-    mkPure $ \_ x ->
-        (Right x, avg' 0 (Seq.replicate n (x ^/ d)) x)
-
-    where
-    avg' :: Int -> Seq v -> v -> Wire e m v v
-    avg' si samples'' a' | si < int = mkPure $ \_ _ -> (Right a', avg' (si + 1) samples'' a')
-    avg' _ samples'' a' =
-        mkPure $ \_ x ->
-            let xa              = x ^/ d
-                xa' :< samples' = viewl samples''
-                samples         = samples' |> xa
-                a               = a' ^-^ xa' ^+^ xa
-            in a `seq` (Right a, avg' 0 samples a)
-
-    d :: Scalar v
-    d = realToFrac n
-
-
--- | Collect all distinct inputs ever received together with a count.
--- Elements not appearing in the map have not been observed yet.
---
--- * Complexity: O(n) space.
---
--- * Depends: current instant.
-
-collect :: forall b m e. (Ord b) => Wire e m b (Map b Int)
-collect = collect' M.empty
-    where
-    collect' :: Map b Int -> Wire e m b (Map b Int)
-    collect' m' =
-        mkPure $ \_ x ->
-            let m = M.insertWith (+) x 1 m' in
-            m `seq` (Right m, collect' m)
-
-
--- | Outputs the first local time the input was seen.
---
--- * Complexity: O(n) space, O(log n) time wrt number of samples so far.
---
--- * Depends: current instant, time.
-
-firstSeen :: forall a m e. (Ord a) => Wire e m a Time
-firstSeen = seen' 0 M.empty
-    where
-    seen' :: Time -> Map a Time -> Wire e m a Time
-    seen' t' m' =
-        mkPure $ \dt x ->
-            let t = t' + dt in
-            t `seq`
-            case M.lookup x m' of
-              Just xt -> (Right xt, seen' t m')
-              Nothing ->
-                  let m = M.insert x t m' in
-                  m `seq` (Right t, seen' t m)
-
-
--- | High peak.
---
--- * Depends: current instant.
-
-highPeak :: (Ord b) => Wire e m b b
-highPeak = peakBy compare
-
-
--- | Outputs the local time the input was previously seen.
---
--- * Complexity: O(n) space, O(log n) time wrt number of samples so far.
---
--- * Depends: current instant, time.
---
--- * Inhibits: if this is the first time the input is seen.
-
-lastSeen :: forall a m e. (Monoid e, Ord a) => Wire e m a Time
-lastSeen = seen' 0 M.empty
-    where
-    seen' :: Time -> Map a Time -> Wire e m a Time
-    seen' t' m' =
-        mkPure $ \dt x ->
-            let t = t' + dt
-                m = M.insert x t m' in
-            t `seq` m `seq`
-            case M.lookup x m' of
-              Just xt -> (Right xt, seen' t m)
-              Nothing -> (Left mempty, seen' t m)
-
-
--- | Low peak.
---
--- * Depends: current instant.
-
-lowPeak :: (Ord b) => Wire e m b b
-lowPeak = peakBy (flip compare)
-
-
--- | Output the peak with respect to the given comparison function.
---
--- * Depends: current instant.
-
-peakBy :: forall b m e. (b -> b -> Ordering) -> Wire e m b b
-peakBy f = mkPure $ \_ x -> (Right x, peak' x)
-    where
-    peak' :: b -> Wire e m b b
-    peak' x' =
-        mkPure $ \_ x ->
-            case f x' x of
-              GT -> (Right x', peak' x')
-              _  -> (Right x, peak' x)
diff --git a/Control/Wire/Prefab/Effect.hs b/Control/Wire/Prefab/Effect.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Effect.hs
+++ /dev/null
@@ -1,117 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Effect
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Effectful wires.
-
-module Control.Wire.Prefab.Effect
-    ( -- * Monadic effects
-      -- ** Simple
-      perform,
-      -- ** Exception-aware
-      execute,
-      execute_,
-      executeWith,
-      executeWith_,
-
-      -- * Branching
-      branch,
-      quit,
-      quitWith
-    )
-    where
-
-import qualified Data.Bifunctor as Bi
-import Control.Exception.Lifted
-import Control.Monad
-import Control.Monad.Trans.Control
-import Control.Wire.Types
-import Control.Wire.Wire
-import Data.List
-import Data.Monoid
-
-
--- | Branch according to the unterlying 'MonadPlus' instance.  Note that
--- this wire branches at every instant.
---
--- * Depends: current instant.
-
-branch :: (MonadPlus m) => Wire e m [a] a
-branch = mkFixM $ \_ -> liftM Right . foldl' mplus mzero . map return
-
-
--- | Variant of 'executeWith' for the 'LastException' inhibition monoid.
---
--- * Depends: current instant.
---
--- * Inhibits: when the action throws an exception.
-
-execute ::
-    (MonadBaseControl IO m)
-    => Wire LastException m (m a) a
-execute = executeWith (Last . Just)
-
-
--- | Variant of 'executeWith_' for the 'LastException' inhibition monoid.
---
--- * Depends: current instant, if the given function is strict.
---
--- * Inhibits: when the action throws an exception.
-
-execute_ ::
-    (MonadBaseControl IO m)
-    => (a -> m b)
-    -> Wire LastException m a b
-execute_ = executeWith_ (Last . Just)
-
-
--- | Perform the input monadic action at every instant.
---
--- * Depends: current instant.
---
--- * Inhibits: when the action throws an exception.
-
-executeWith ::
-    (MonadBaseControl IO m)
-    => (SomeException -> e)  -- ^ Turns an exception into an inhibition value.
-    -> Wire e m (m a) a
-executeWith fromEx = mkFixM $ \_ c -> liftM (Bi.first fromEx) (try c)
-
-
--- | Perform the given monadic action at every instant.
---
--- * Depends: current instant, if the given function is strict.
---
--- * Inhibits: when the action throws an exception.
-
-executeWith_ ::
-    (MonadBaseControl IO m)
-    => (SomeException -> e)  -- ^ Turns an exception into an inhibition value.
-    -> (a -> m b)            -- ^ Action to perform.
-    -> Wire e m a b
-executeWith_ fromEx c = mkFixM $ \_ -> liftM (Bi.first fromEx) . try . c
-
-
--- | Perform the input monadic action in a wire.
---
--- * Depends: current instant.
-
-perform :: (Monad m) => Wire e m (m b) b
-perform = mkFixM . const $ liftM Right
-
-
--- | Quits the current branch using 'mzero'.
-
-quit :: (MonadPlus m) => Wire e m a b
-quit = mkFixM $ \_ _ -> mzero
-
-
--- | Acts like identity in the first instant, then quits the current
--- branch using 'mzero'.
---
--- * Depends: first instant.
-
-quitWith :: (MonadPlus m) => Wire e m a a
-quitWith = mkPure $ \_ x -> (Right x, quit)
diff --git a/Control/Wire/Prefab/Event.hs b/Control/Wire/Prefab/Event.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Event.hs
+++ /dev/null
@@ -1,307 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Event
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Event wires.
-
-module Control.Wire.Prefab.Event
-    ( -- * Instants
-      afterI,
-      eventsI,
-      forI,
-      notYet,
-      once,
-      periodicallyI,
-
-      -- * Signal analysis
-      changed,
-      inject,
-      -- ** Predicate-based
-      asSoonAs,
-      edge,
-      forbid,
-      require,
-      unless,
-      until,
-      when,
-      while,
-
-      -- * Time
-      after,
-      events,
-      for,
-      periodically,
-
-      -- * Utilities
-      inhibit
-    )
-    where
-
-import Control.Category
-import Control.Wire.Classes
-import Control.Wire.Types
-import Control.Wire.Wire
-import Data.Monoid
-import Prelude hiding ((.), id, until)
-
-
--- | Produce after the given amount of time.
---
--- * Depends: current instant when producing, time.
---
--- * Inhibits: until the given amount of time has passed.
-
-after :: (Monoid e) => Time -> Event e m a
-after t
-    | t <= 0     = identity
-    | otherwise = mkPure $ \dt _ -> (Left mempty, after (t - dt))
-
-
--- | Produce after the given number of instants.
---
--- * Depends: current instant when producing.
---
--- * Inhibits: until the given number of instants has passed.
-
-afterI :: (Monoid e) => Int -> Event e m a
-afterI t
-    | t <= 0     = identity
-    | otherwise = mkPure $ \_ _ -> (Left mempty, afterI (t - 1))
-
-
--- | Inhibit until the given predicate holds for the input signal.  Then
--- produce forever.
---
--- * Depends: current instant, if the predicate is strict.  Once true,
--- on current instant forever.
---
--- * Inhibits: until the predicate becomes true.
-
-asSoonAs :: (Monoid e) => (a -> Bool) -> Event e m a
-asSoonAs p =
-    mkPure $ \_ x ->
-        if p x
-          then (Right x, identity)
-          else (Left mempty, asSoonAs p)
-
-
--- | Produce when the signal has changed and at the first instant.
---
--- * Depends: current instant.
---
--- * Inhibits: after the first instant when the input has changed.
-
-changed :: (Eq a, Monoid e) => Event e m a
-changed = mkPure $ \_ x0 -> (Right x0, changed' x0)
-    where
-    changed' x' =
-        mkPure $ \_ x ->
-            (if x' == x then Left mempty else Right x,
-             changed' x)
-
-
--- | Produces once whenever the given predicate switches from 'False' to
--- 'True'.
---
--- * Depends: current instant.
---
--- * Inhibits: when the predicate has not just switched from 'False' to
--- 'True'.
-
-edge :: (Monoid e) => (a -> Bool) -> Event e m a
-edge p = off
-    where
-    off = mkPure $ \_ x -> if p x then (Right x, on) else (Left mempty, off)
-    on  = mkPure $ \_ x -> (Left mempty, if p x then on else off)
-
-
--- | Produce once periodically.  The production periods are given by the
--- argument list.  When it's @[1,2,3]@ it produces after one second,
--- then after two more seconds and finally after three more seconds.
--- When the list is exhausted, it never produces again.
---
--- * Depends: current instant when producing, time.
---
--- * Inhibits: between the given intervals.
-
-events :: (Monoid e) => [Time] -> Event e m a
-events [] = never
-events (t':ts) =
-    mkPure $ \dt x ->
-        let t = t' - dt in
-        if t <= 0
-          then (Right x, events (mapHead (+ t) ts))
-          else (Left mempty, events (t:ts))
-
-    where
-    mapHead :: (a -> a) -> [a] -> [a]
-    mapHead _ []     = []
-    mapHead f (x:xs) = f x : xs
-
-
--- | Variant of 'periodically' in number of instants instead of amount
--- of time.
---
--- * Depends: current instant when producing.
---
--- * Inhibits: between the given intervals.
-
-eventsI :: (Monoid e) => [Int] -> Event e m a
-eventsI [] = never
-eventsI (0:ts) = mkPure $ \_ x -> (Right x, eventsI ts)
-eventsI (t:ts) = mkPure $ \_ _ -> (Left mempty, eventsI (t - 1 : ts))
-
-
--- | Produce for the given amount of time.
---
--- * Depends: current instant when producing, time.
---
--- * Inhibits: after the given amount of time has passed.
-
-for :: (Monoid e) => Time -> Event e m a
-for t
-    | t <= 0     = never
-    | otherwise = mkPure $ \dt x -> (Right x, for (t - dt))
-
-
--- | Same as 'unless'.
-
-forbid :: (Monoid e) => (a -> Bool) -> Event e m a
-forbid = unless
-
-
--- | Produce for the given number of instants.
---
--- * Depends: current instant when producing.
---
--- * Inhibits: after the given number of instants has passed.
-
-forI :: (Monoid e) => Int -> Event e m a
-forI t
-    | t <= 0     = never
-    | otherwise = mkPure $ \_ x -> (Right x, forI (t - 1))
-
-
--- | Inhibit with the given value.  You may want to use a combination of
--- 'Control.Applicative.empty' and 'Control.Wire.Trans.Event.<!>'
--- instead.
---
--- * Inhibits: always.
-
-inhibit :: e -> Wire e m a b
-inhibit ex = mkFix (\_ _ -> Left ex)
-
-
--- | Inject the input signal.  Please keep in mind that in application
--- code it is almost always wrong to use this wire.  It should only be
--- used to interact with other frameworks/abstractions, and even then
--- it's probably just a last resort.
---
--- When you want to write your own wires, consider using 'mkPure' or the
--- various variants of it.
---
--- * Depends: current instant.
---
--- * Inhibits: depending on input signal (see 'Injectable').
-
-inject :: (Injectable e f) => Wire e m (f b) b
-inject = mkFix (const toSignal)
-
-
--- | Inhibit once.
---
--- * Depends: current instant after the first instant.
---
--- * Inhibits: in the first instant.
-
-notYet :: (Monoid e) => Event e m a
-notYet = mkPure $ \_ _ -> (Left mempty, identity)
-
-
--- | Produce once.
---
--- * Depends: current instant in the first instant.
---
--- * Inhibits: after the first instant.
-
-once :: (Monoid e) => Event e m a
-once = mkPure $ \_ x -> (Right x, never)
-
-
--- | Produce once periodically with the given time interval.
---
--- * Depends: current instant when producing, time.
---
--- * Inhibits: between the intervals.
-
-periodically :: (Monoid e) => Time -> Event e m a
-periodically = events . repeat
-
-
--- | Produce once periodically with the given number of instants as the
--- interval.
---
--- * Depends: current instant when producing.
---
--- * Inhibits: between the intervals.
-
-periodicallyI :: (Monoid e) => Int -> Event e m a
-periodicallyI = eventsI . repeat
-
-
--- | Same as 'when'.
-
-require :: (Monoid e) => (a -> Bool) -> Event e m a
-require = when
-
-
--- | Produce when the given predicate on the input signal does not hold.
---
--- * Depends: current instant if the predicate is strict.
---
--- * Inhibits: When the predicate is true.
-
-unless :: (Monoid e) => (a -> Bool) -> Event e m a
-unless p =
-    mkFix $ \_ x ->
-        if p x then Left mempty else Right x
-
-
--- | Produce until the given predicate on the input signal holds, then
--- inhibit forever.
---
--- * Depends: current instant, if the predicate is strict.
---
--- * Inhibits: forever as soon as the predicate becomes true.
-
-until :: (Monoid e) => (a -> Bool) -> Event e m a
-until p = while (not . p)
-
-
--- | Produce when the given predicate on the input signal holds.
---
--- * Depends: current instant if the predicate is strict.
---
--- * Inhibits: When the predicate is false.
-
-when :: (Monoid e) => (a -> Bool) -> Event e m a
-when p =
-    mkFix $ \_ x ->
-        if p x then Right x else Left mempty
-
-
--- | Produce while the given predicate on the input signal holds, then
--- inhibit forever.
---
--- * Depends: current instant, if the predicate is strict.
---
--- * Inhibits: forever as soon as the predicate becomes false.
-
-while :: (Monoid e) => (a -> Bool) -> Event e m a
-while p =
-    mkPure $ \_ x ->
-        if p x
-          then (Right x, while p)
-          else (Left mempty, never)
diff --git a/Control/Wire/Prefab/List.hs b/Control/Wire/Prefab/List.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/List.hs
+++ /dev/null
@@ -1,36 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.List
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Wires from lists.
-
-module Control.Wire.Prefab.List
-    ( -- * Wires from lists
-      cycleW,
-      list
-    )
-    where
-
-import Control.Applicative
-import Control.Monad.Fix
-import Control.Wire.Wire
-import Data.Monoid
-
-
--- | Produce the values in the given list cycling forever.
---
--- * Inhibits: when the argument list is empty.
-
-cycleW :: (Monad m, Monoid e) => [b] -> Wire e m a b
-cycleW [] = empty
-cycleW xs = fix (\again -> foldr cons again xs)
-
-
--- | Produce the values in the given list and then inhibit forever.
---
--- * Inhibits: when the list is exhausted.
-
-list :: (Monad m, Monoid e) => [b] -> Wire e m a b
-list = foldr cons empty
diff --git a/Control/Wire/Prefab/Move.hs b/Control/Wire/Prefab/Move.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Move.hs
+++ /dev/null
@@ -1,247 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Move
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- This module provides the wires for various kinds of moving objects.
--- In particular this includes various calculus wires like integrals and
--- differentials.
-
-module Control.Wire.Prefab.Move
-    ( -- * Calculus
-      -- ** Integrals
-      integral,
-      integral_,
-      integralLim,
-      integralLim_,
-      integral1,
-      integral1_,
-      integralLim1,
-      integralLim1_,
-      -- ** Differentials
-      derivative,
-      derivative_,
-
-      -- * Simulations/games
-      object,
-      object_,
-      ObjectState(..),
-      ObjectDiff(..)
-    )
-    where
-
-import Control.Applicative
-import Control.Arrow
-import Control.Category
-import Control.Wire.Prefab.Accum
-import Control.Wire.Prefab.Time
-import Control.Wire.Wire
-import Data.Data
-import Data.VectorSpace
-import Prelude hiding ((.), id)
-
-
--- | Object state.  This includes the position and velocity.
-
-data ObjectState a =
-    ObjectState {
-      objPosition :: a,  -- ^ Position.
-      objVelocity :: a   -- ^ Velocity.
-    }
-    deriving (Data, Eq, Ord, Read, Show, Typeable)
-
-
--- | Differential for objects.
-
-data ObjectDiff a
-    -- | Accelerate (units per second).
-    = Accelerate a
-
-    -- | Teleport to the given position instantly (velocity will be
-    -- unchanged).
-    | Position a
-
-    -- | Specify velocity (units per second).
-    | Velocity a
-    deriving (Data, Eq, Ord, Read, Show, Typeable)
-
-
--- | Derivative.  Receives @x@ and @dt@ and calculates the change rate
--- @dx/dt@.  Note that @dt@ despite its name does not have to be time.
---
--- The exception handler function is called when @dt@ is zero.  That
--- function's result is the wire's output for those instants.  If you
--- don't want to handle exceptional cases specially, just pass @(^/)@ as
--- the handler function.
---
--- * Depends: current instant.
-
-derivative ::
-    (Eq dt, Fractional dt, VectorSpace b, Scalar b ~ dt)
-    => (b -> dt -> b)  -- ^ Handle exceptional change rates (receives dx and dt).
-    -> b               -- ^ Initial position.
-    -> Wire e m (b, dt) b
-derivative catch x0 =
-    mkPure $ \_ (x1, dt) ->
-        let dx = x1 ^-^ x0
-            d | dt == 0    = catch dx dt
-              | otherwise = dx ^/ dt
-        in (Right d, derivative catch x1)
-
-
--- | Same as 'derivative', but with respect to time.
---
--- * Depends: current instant.
-
-derivative_ ::
-    (Monad m, VectorSpace b, Scalar b ~ Time)
-    => (b -> Time -> b)  -- ^ Handle exceptional cases.
-    -> b                 -- ^ Initial position.
-    -> Wire e m b b
-derivative_ catch x0 = derivative catch x0 . (id &&& dtime)
-
-
--- | Integral wire.  Produces position from velocity in the sense of the
--- given vector space.
---
--- * Depends: previous instant.
-
-integral ::
-    (VectorSpace b)
-    => b
-    -> Wire e m (b, Scalar b) b
-integral = accum (\x (dx, dt) -> x ^+^ dt *^ dx)
-
-
--- | Non-delaying variant of 'integral'.
---
--- * Depends: current instant.
-
-integral1 ::
-    (VectorSpace b)
-    => b
-    -> Wire e m (b, Scalar b) b
-integral1 = accum1 (\x (dx, dt) -> x ^+^ dt *^ dx)
-
-
--- | Same as 'integral', but with respect to time.
---
--- * Depends: previous instant.
-
-integral_ ::
-    (VectorSpace b, Scalar b ~ Time)
-    => b
-    -> Wire e m b b
-integral_ = accumT (\dt x dx -> x ^+^ dt *^ dx)
-
-
--- | Non-delaying variant of 'integral_'.
---
--- * Depends: current instant.
-
-integral1_ ::
-    (Monad m, VectorSpace b, Scalar b ~ Time)
-    => b
-    -> Wire e m b b
-integral1_ = accumT1 (\dt x dx -> x ^+^ dt *^ dx)
-
-
--- | Variant of 'integral', where you can specify a post-update
--- function, which receives the previous position as well as the current
--- (in that order).  This is useful for limiting the output (think of
--- robot arms that can't be moved freely).
---
--- * Depends: current instant if the post-update function is strict in
--- its first argument, previous instant if not.
-
-integralLim ::
-    (VectorSpace b)
-    => (w -> b -> b -> b)  -- ^ Post-update function.
-    -> b                   -- ^ Initial value.
-    -> Wire e m ((b, w), Scalar b) b
-integralLim uf = accum (\x ((dx, w), dt) -> uf w x (x ^+^ dt *^ dx))
-
-
--- | Non-delaying variant of 'integralLim'.
---
--- * Depends: current instant.
-
-integralLim1 ::
-    (VectorSpace b)
-    => (w -> b -> b -> b)  -- ^ Post-update function.
-    -> b                   -- ^ Initial value.
-    -> Wire e m ((b, w), Scalar b) b
-integralLim1 uf = accum1 (\x ((dx, w), dt) -> uf w x (x ^+^ dt *^ dx))
-
-
--- | Same as 'integralLim', but with respect to time.
---
--- * Depends: previous instant.
-
-integralLim_ ::
-    (VectorSpace b, Scalar b ~ Time)
-    => (w -> b -> b -> b)
-    -> b
-    -> Wire e m (b, w) b
-integralLim_ uf = accumT (\dt x (dx, w) -> uf w x (x ^+^ dt *^ dx))
-
-
--- | Non-delaying variant of 'integralLim_'.
---
--- * Depends: current instant.
-
-integralLim1_ ::
-    (VectorSpace b, Scalar b ~ Time)
-    => (w -> b -> b -> b)
-    -> b
-    -> Wire e m (b, w) b
-integralLim1_ uf = accumT1 (\dt x (dx, w) -> uf w x (x ^+^ dt *^ dx))
-
-
--- | Objects are generalized integrals.  They are controlled through
--- velocity and/or acceleration and can be collision-checked as well as
--- instantly teleported.
---
--- The post-move update function receives the world state and the
--- current object state.  It is applied just before the wire produces
--- its output.  You can use it to perform collision-checks or to limit
--- the velocity.
---
--- Note that teleportation doesn't change the velocity.
---
--- * Depends: current instant.
-
-object ::
-    forall b m dt e w.
-    (VectorSpace b, Scalar b ~ dt)
-    => (w -> ObjectState b -> ObjectState b)  -- ^ Post-move update function.
-    -> ObjectState b                          -- ^ Initial state.
-    -> Wire e m (ObjectDiff b, w, dt) (ObjectState b)
-object uf = loop
-    where
-    applyDiff :: dt -> ObjectDiff b -> ObjectState b -> ObjectState b
-    applyDiff dt (Accelerate dv) (ObjectState x' v') = ObjectState x v
-        where
-        v = v' ^+^ dt *^ dv
-        x = x' ^+^ dt *^ v
-    applyDiff _  (Position x) (ObjectState _ v)  = ObjectState x v
-    applyDiff dt (Velocity v) (ObjectState x' _) = ObjectState (x' ^+^ dt *^ v) v
-
-    loop :: ObjectState b -> Wire e m (ObjectDiff b, w, dt) (ObjectState b)
-    loop os' =
-        mkPure $ \_ (dos, w, dt) ->
-            let os = uf w . applyDiff dt dos $ os'
-            in (Right os, loop os)
-
-
--- | Same as 'object', but with respect to time.
---
--- * Depends: current instant.
-
-object_ ::
-    (Monad m, VectorSpace b, Scalar b ~ Time)
-    => (w -> ObjectState b -> ObjectState b)  -- ^ Post-move update function.
-    -> ObjectState b                          -- ^ Initial state.
-    -> Wire e m (ObjectDiff b, w) (ObjectState b)
-object_ uf x0 = object uf x0 . liftA2 (\(dx, w) dt -> (dx, w, dt)) id dtime
diff --git a/Control/Wire/Prefab/Noise.hs b/Control/Wire/Prefab/Noise.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Noise.hs
+++ /dev/null
@@ -1,96 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Noise
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Various noise generators.
-
-module Control.Wire.Prefab.Noise
-    ( -- * Pure random noise
-      noise,
-      noiseR,
-      wackelkontakt,
-
-      -- * Effectful random noise
-      noiseM,
-      noiseRM,
-      wackelkontaktM
-    )
-    where
-
-import Control.Monad
-import Control.Wire.Classes
-import Control.Wire.Prefab.Accum
-import Control.Wire.Types
-import Control.Wire.Wire
-import Data.Monoid
-import System.Random
-
-
--- | Pure noise generator.
-
-noise ::
-    (Random b, RandomGen g)
-    => g  -- ^ Initial random number generator.
-    -> Wire e m a b
-noise = unfold (\g' _ -> random g')
-
-
--- | Noise generator.
-
-noiseM ::
-    (MonadRandom m, Random b)
-    => Wire e m a b
-noiseM =
-    mkFixM $ \_ _ -> liftM (Right $!) getRandom
-
-
--- | Ranged noise generator.
---
--- * Depends: current instant.
-
-noiseRM ::
-    (MonadRandom m, Random b)
-    => Wire e m (b, b) b
-noiseRM = mkFixM $ \_ -> liftM (Right $!) . getRandomR
-
-
--- | Pure ranged noise generator.
---
--- * Depends: current instant.
-
-noiseR ::
-    (Random b, RandomGen g)
-    => g  -- ^ Initial random number generator.
-    -> Wire e m (b, b) b
-noiseR = unfold (\g' r -> randomR r g')
-
-
--- | Event:  Occurs randomly with the given probability.
---
--- * Inhibits: @wackelkontaktM p@ inhibits with probability @1 - p@.
-
-wackelkontakt ::
-    (Monoid e, RandomGen g)
-    => Double  -- ^ Occurrence probability.
-    -> g  -- ^ Initial random number generator.
-    -> Event e m a
-wackelkontakt p g' =
-    mkPure $ \_ x ->
-        let (e, g) = random g' in
-        (if (e < p) then Right x else Left mempty, wackelkontakt p g)
-
-
--- | Event:  Occurs randomly with the given probability.
---
--- * Inhibits: @wackelkontaktM p@ inhibits with probability @1 - p@.
-
-wackelkontaktM ::
-    (MonadRandom m, Monoid e)
-    => Double  -- ^ Occurrence probability.
-    -> Event e m a
-wackelkontaktM p =
-    mkFixM $ \_ x -> do
-        e <- getRandom
-        return (if (e < p) then Right x else Left mempty)
diff --git a/Control/Wire/Prefab/Queue.hs b/Control/Wire/Prefab/Queue.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Queue.hs
+++ /dev/null
@@ -1,88 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Queue
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Wires acting as queues.
-
-module Control.Wire.Prefab.Queue
-    ( -- * Queues
-      bag,
-      fifo,
-      lifo
-    )
-    where
-
-import qualified Data.Set as S
-import qualified Data.Sequence as Seq
-import Control.Wire.Wire
-import Data.Monoid
-import Data.Set (Set)
-import Data.Sequence (ViewL(..), (><), viewl)
-
-
--- | Incoming values are placed in a set, which is discharged element by
--- element.  Lower values are served first.  Duplicate values are served
--- once.
---
--- Note: Incorrect usage can lead to congestion.
---
--- * Complexity: O(n) space wrt bag size.
---
--- * Depends: current instant.
---
--- * Inhibits: when the bag is empty.
-
-bag :: (Monoid e, Ord b) => Wire e m (Set b) b
-bag = bag' S.empty
-    where
-    bag' s' =
-        mkPure $ \_ xs ->
-            case S.minView (S.union s' xs) of
-              Nothing     -> (Left mempty, bag' S.empty)
-              Just (x, s) -> (Right x, bag' s)
-
-
--- | First in, first out.  The input list is placed on the right end of
--- a queue at every instant, giving earlier elements a higher priority.
--- The queue is discharged item by item from the left.
---
--- Note: Incorrect usage can lead to congestion.
---
--- * Complexity: O(n) space wrt queue size.
---
--- * Depends: current instant.
---
--- * Inhibits: when the queue is currently empty.
-
-fifo :: (Monoid e) => Wire e m [b] b
-fifo = fifo' Seq.empty
-    where
-    fifo' queue' =
-        mkPure $ \_ xs ->
-            case viewl (queue' >< Seq.fromList xs) of
-              EmptyL     -> (Left mempty, fifo' Seq.empty)
-              x :< queue -> (Right x, fifo' queue)
-
-
--- | Last in, first out.  The input list is placed on a stack at every
--- instant, giving earlier elements a higher priority.  The stack is
--- discharged item by item from the top.
---
--- Note: Incorrect usage can lead to congestion.
---
--- * Complexity: O(n) space wrt stack size.
---
--- * Depends: current instant.
---
--- * Inhibits: when the stack is currently empty.
-
-lifo :: (Monoid e) => Wire e m [b] b
-lifo = lifo' Seq.empty
-    where
-    lifo' queue' =
-        mkPure $ \_ xs ->
-            case viewl (Seq.fromList xs >< queue') of
-              EmptyL     -> (Left mempty, lifo' Seq.empty)
-              x :< queue -> (Right x, lifo' queue)
diff --git a/Control/Wire/Prefab/Sample.hs b/Control/Wire/Prefab/Sample.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Sample.hs
+++ /dev/null
@@ -1,85 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Sample
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Signal sampling wires.
-
-module Control.Wire.Prefab.Sample
-    ( -- * Sampling
-      --history,
-      keep,
-      sample,
-      window,
-      windowList
-    )
-    where
-
-import qualified Data.Foldable as F
-import qualified Data.Sequence as Seq
-import Control.Wire.Wire
-import Data.Sequence (Seq, (|>))
-
-
--- | Produce the most recent inputs in the given time window.  The left
--- input signal is the sample, the right input signal is the time
--- window.
---
--- * Complexity: O(n), where n the number of samples in the time window.
---
--- * Depends: current instant.
-
---history :: (Reactive cat) => Wire e cat (a, Time) (Seq (a, Time))
---history = undefined
-
-
--- | Keep the input signal of the first instant forever.
---
--- Depends: first instant.
-
-keep :: Wire e m a a
-keep = mkPure (\_ x -> (Right x, constant x))
-
-
--- | Sample the left signal at discrete intervals given by the right
--- signal.
---
--- * Depends: instant of the last sample.
-
-sample :: Wire e m (a, Time) a
-sample = mkPure $ \dt (x, _) -> (Right x, sample' dt x)
-    where
-    sample' t0' x' =
-        mkPure $ \dt (x, t1) ->
-            let t0 = t0' + dt in
-            if t0 >= t1
-              then (Right x, sample' (t0 - t1) x)
-              else (Right x', sample' t0 x')
-
-
--- | Produce up to the given number of most recent inputs.
---
--- * Complexity: O(n), where n is the given argument.
---
--- * Depends: current instant.
-
-window :: Int -> Wire e m a (Seq a)
-window = collect' Seq.empty
-    where
-    collect' s' 0 = window' s'
-    collect' s' n =
-        mkPure $ \_ x ->
-            let s = s' |> x in
-            s `seq` (Right s, collect' s (n - 1))
-
-    window' s' =
-        mkPure $ \_ x ->
-            let s = Seq.drop 1 (s' |> x) in
-            s `seq` (Right s, window' s)
-
-
--- | Same as @fmap toList . window@.
-
-windowList :: (Monad m) => Int -> Wire e m a [a]
-windowList = fmap F.toList . window
diff --git a/Control/Wire/Prefab/Simple.hs b/Control/Wire/Prefab/Simple.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Simple.hs
+++ /dev/null
@@ -1,67 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Simple
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Basic wires.
-
-module Control.Wire.Prefab.Simple
-    ( -- * Basic signal manipulation
-      append,
-      delay,
-      prepend,
-
-      -- * Forcing evaluation
-      force,
-      forceNF
-    )
-    where
-
-import Control.Arrow
-import Control.Category
-import Control.DeepSeq (NFData, ($!!))
-import Control.Wire.Wire
-import Prelude hiding ((.), id)
-
-
--- | Convenience function to add another signal.
---
--- * Depends: current instant.
-
-append :: (Monad m) => Wire e m a b -> Wire e m a (a, b)
-append = (id &&&)
-
-
--- | One-instant delay.
---
--- * Depends: previous instant.
-
-delay :: a -> Wire e m a a
-delay x' = mkPure (\_ x -> x' `seq` (Right x', delay x))
-
-
--- | Acts like the identity wire, but forces evaluation of the signal to
--- WHNF.
---
--- * Depends: current instant.
-
-force :: Wire e m a a
-force = mkFix (\_ -> (Right $!))
-
-
--- | Acts like the identity wire, but forces evaluation of the signal to
--- NF.
---
--- * Depends: current instant.
-
-forceNF :: (NFData a) => Wire e m a a
-forceNF = mkFix (\_ -> (Right $!!))
-
-
--- | Convenience function to add another signal.
---
--- * Depends: current instant.
-
-prepend :: (Monad m) => Wire e m a b -> Wire e m a (b, a)
-prepend = (&&& id)
diff --git a/Control/Wire/Prefab/Time.hs b/Control/Wire/Prefab/Time.hs
deleted file mode 100644
--- a/Control/Wire/Prefab/Time.hs
+++ /dev/null
@@ -1,45 +0,0 @@
--- |
--- Module:     Control.Wire.Prefab.Time
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Time wires.
-
-module Control.Wire.Prefab.Time
-    ( -- * Time
-      dtime,
-      time,
-      timeFrom
-    )
-    where
-
-import Control.Wire.Wire
-
-
--- | Outputs the time delta to the last instant.
---
--- * Depends: time.
-
-dtime :: Wire e m a Time
-dtime = mkFix (\dt _ -> Right dt)
-
-
--- | Outputs the current local time passed since the first instant.
---
--- * Depends: time.
-
-time :: Wire e m a Time
-time = timeFrom 0
-
-
--- | Outputs the current local time passed since the first instant with
--- the given offset.
---
--- * Depends: time.
-
-timeFrom :: Time -> Wire e m a Time
-timeFrom t' =
-    mkPure $ \dt _ ->
-        let t = t' + dt in
-        t `seq` (Right t, timeFrom t)
diff --git a/Control/Wire/Run.hs b/Control/Wire/Run.hs
new file mode 100644
--- /dev/null
+++ b/Control/Wire/Run.hs
@@ -0,0 +1,63 @@
+-- |
+-- Module:     Control.Wire.Run
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Control.Wire.Run
+    ( -- * Testing wires
+      testWire,
+      testWireM
+    )
+    where
+
+import Control.Monad.IO.Class
+import Control.Wire.Core
+import Control.Wire.Session
+import Data.Functor.Identity
+import System.IO
+
+
+-- | This function runs the given wire using the given state delta
+-- generator.  It constantly shows the output of the wire on one line on
+-- stdout.  Press Ctrl-C to abort.
+
+testWire ::
+    (MonadIO m, Show b, Show e)
+    => Session m s
+    -> (forall a. Wire s e Identity a b)
+    -> m c
+testWire s0 w0 = loop s0 w0
+    where
+    loop s' w' = do
+        (ds, s) <- stepSession s'
+        let Identity (mx, w) = stepWire w' ds (Right ())
+        liftIO $ do
+            putChar '\r'
+            putStr (either (\ex -> "I: " ++ show ex) show mx)
+            putStr "\027[K"
+            hFlush stdout
+        loop s w
+
+
+-- | This function runs the given wire using the given state delta
+-- generator.  It constantly shows the output of the wire on one line on
+-- stdout.  Press Ctrl-C to abort.
+
+testWireM ::
+    (Monad m', MonadIO m, Show b, Show e)
+    => (forall a. m' a -> m a)
+    -> Session m s
+    -> (forall a. Wire s e m' a b)
+    -> m c
+testWireM run s0 w0 = loop s0 w0
+    where
+    loop s' w' = do
+        (ds, s) <- stepSession s'
+        (mx, w) <- run (stepWire w' ds (Right ()))
+        liftIO $ do
+            putChar '\r'
+            putStr (either (\ex -> "I: " ++ show ex) show mx)
+            putStr "\027[K"
+            hFlush stdout
+        loop s w
diff --git a/Control/Wire/Session.hs b/Control/Wire/Session.hs
--- a/Control/Wire/Session.hs
+++ b/Control/Wire/Session.hs
@@ -1,239 +1,111 @@
 -- |
 -- Module:     Control.Wire.Session
--- Copyright:  (c) 2012 Ertugrul Soeylemez
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
 -- License:    BSD3
 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Wire sessions.
 
 module Control.Wire.Session
-    ( -- * Performing instants
-      stepSession,
-      stepSession_,
-      stepSessionP,
-      stepSessionP_,
-
-      -- * Testing wires
-      testWire,
-      testWireP,
-      -- ** Helper functions
-      testPrint,
-
-      -- * Sessions
+    ( -- * State delta types
+      HasTime(..),
       Session(..),
-      -- ** Generic sessions
-      genSession,
-      -- ** Specific session types
+
+      -- ** Wires with time
+      Timed(..),
       clockSession,
-      counterSession,
-      frozenSession
+      clockSession_,
+      countSession,
+      countSession_
     )
     where
 
-import Control.Concurrent
-import Control.Exception
-import Control.Monad
-import Control.Monad.Identity
-import Control.Monad.Trans
-import Control.Wire.Types
-import Control.Wire.Wire
+import Control.Applicative
+import Control.Monad.IO.Class
+import Data.Data
+import Data.Foldable (Foldable)
 import Data.Monoid
 import Data.Time.Clock
-import System.IO
-
-
--- | A session value contains time-related information.
-
-newtype Session m =
-    Session {
-      sessionUpdate :: m (Time, Session m)
-    }
-
-
--- | Construct a session using real time.  This session type uses
--- 'getCurrentTime'.  If you have a faster time source, you may want to
--- use 'genSession' instead and construct your own clock.
-
-clockSession :: (MonadIO m) => Session m
-clockSession =
-    Session $ do
-        t0 <- liftIO getCurrentTime
-        return (0, loop t0)
-
-    where
-    loop t' =
-        Session $ do
-            t <- liftIO getCurrentTime
-            let dt = realToFrac (diffUTCTime t t')
-            return (dt, loop t)
-
-
--- | Construct a simple counter session.  The time delta is the given
--- argument at every instant.
-
-counterSession ::
-    (Monad m)
-    => Time  -- ^ Time delta for every instant.
-    -> Session m
-counterSession dt =
-    let s = Session (return (dt, s)) in s
+import Data.Traversable (Traversable)
 
 
--- | Construct a frozen session.  Same as @'counterSession' 0@.
+-- | State delta types with time deltas.
 
-frozenSession :: (Monad m) => Session m
-frozenSession = counterSession 0
+class (Monoid s, Real t) => HasTime t s | s -> t where
+    -- | Extract the current time delta.
+    dtime :: s -> t
 
 
--- | Construct a generic session from the given initial session value
--- and the update function.  You can use this function to implement your
--- own clock.
---
--- If you just want to use real time, you may want to use
--- 'clockSession'.
-
-genSession ::
-    (Monad m)
-    => a
-    -> (a -> m (Time, a))
-    -> Session m
-genSession s' f =
-    Session $ do
-        (t, s) <- f s'
-        return (t, genSession s f)
+-- | State delta generators as required for wire sessions, most notably
+-- to generate time deltas.  These are mini-wires with the sole purpose
+-- of generating these deltas.
 
+newtype Session m s =
+    Session {
+      stepSession :: m (s, Session m s)
+    }
+    deriving (Functor)
 
--- | Perform an instant of the given wire as part of a wire session.
---
--- This is a convenience function.  You can also construct time deltas
--- yourself entirely circumventing 'Session'.  This can be useful, if
--- there is really no need for an effectful monad.
+instance (Applicative m) => Applicative (Session m) where
+    pure x = let s = Session (pure (x, s)) in s
 
-stepSession ::
-    (MonadIO m)
-    => Wire e m a b  -- ^ Wire to step.
-    -> Session m     -- ^ Current session state.
-    -> a             -- ^ Input value.
-    -> m (Either e b, Wire e m a b, Session m)
-stepSession w' (Session update) x' = do
-    (dt, s) <- update
-    (mx, w) <- stepWire w' dt x'
-    mx `seq` return (mx, w, s)
+    Session ff <*> Session fx =
+        Session $ liftA2 (\(f, sf) (x, sx) -> (f x, sf <*> sx)) ff fx
 
 
--- | Like 'stepSession', but throws an exception instead of returning an
--- 'Either' value.
-
-stepSession_ ::
-    (MonadIO m)
-    => WireM m a b  -- ^ Wire to step.
-    -> Session m    -- ^ Current session state.
-    -> a            -- ^ Input value.
-    -> m (b, WireM m a b, Session m)
-stepSession_ w' s' x' = do
-    (mx, w, s) <- stepSession w' s' x'
-
-    let throwM   = liftIO . throwIO
-        emptyErr = toException (userError "empty inhibition signal")
-    x <- either (throwM . maybe emptyErr id . getLast) return mx
+-- | This state delta type denotes time deltas.  This is necessary for
+-- most FRP applications.
 
-    return (x, w, s)
+data Timed t s = Timed t s
+    deriving (Data, Eq, Foldable, Functor,
+              Ord, Read, Show, Traversable, Typeable)
 
+instance (Monoid s, Real t) => HasTime t (Timed t s) where
+    dtime (Timed dt _) = dt
 
--- | Like 'stepSession', but for pure wires.
+instance (Monoid s, Num t) => Monoid (Timed t s) where
+    mempty = Timed 0 mempty
 
-stepSessionP ::
-    (Monad m)
-    => Wire e Identity a b  -- ^ Wire to step.
-    -> Session m            -- ^ Current session state.
-    -> a                    -- ^ Input value.
-    -> m (Either e b, Wire e Identity a b, Session m)
-stepSessionP w' (Session update) !x' = do
-    (dt, s) <- update
-    let (mx, w) = stepWireP w' dt x'
-    mx `seq` return (mx, w, s)
+    mappend (Timed dt1 ds1) (Timed dt2 ds2) =
+        let dt = dt1 + dt2
+            ds = ds1 <> ds2
+        in dt `seq` ds `seq` Timed dt ds
 
 
--- | Like 'stepSessionP', but throws an exception instead of returning an
--- 'Either' value.
-
-stepSessionP_ ::
-    (MonadIO m)
-    => WireP a b  -- ^ Wire to step.
-    -> Session m  -- ^ Current session state.
-    -> a          -- ^ Input value.
-    -> m (b, WireP a b, Session m)
-stepSessionP_ w' s' !x' = do
-    (mx, w, s) <- stepSessionP w' s' x'
+-- | State delta generator for a real time clock.
 
-    let throwM   = liftIO . throwIO
-        emptyErr = toException (userError "empty inhibition signal")
-    x <- either (throwM . maybe emptyErr id . getLast) return mx
+clockSession :: (MonadIO m) => Session m (s -> Timed NominalDiffTime s)
+clockSession =
+    Session $ do
+        t0 <- liftIO getCurrentTime
+        return (Timed 0, loop t0)
 
-    return (x, w, s)
+    where
+    loop t' =
+        Session $ do
+            t <- liftIO getCurrentTime
+            let dt = diffUTCTime t t'
+            dt `seq` return (Timed dt, loop t)
 
 
--- | @testPrint n int mx@ prints a formatted version of @mx@ to stderr,
--- if @n@ is zero.  It returns @mod (succ n) int@.  Requires @n >= 0@ to
--- work properly.
---
--- This function is used to implement the /printing interval/ used in
--- 'testWire' and 'testWireM'.
+-- | Non-extending version of 'clockSession'.
 
-testPrint :: (Show e) => Int -> Int -> Either e String -> IO Int
-testPrint n' int mx = do
-    let n = let nn = n' + 1 in
-            if nn >= int then 0 else nn
-    when (n' == 0) $ do
-        hPutStr stderr "\r\027[K"
-        hPutStr stderr (either (("(I) " ++) . show) id mx)
-        hFlush stderr
-    n `seq` return n
+clockSession_ :: (Applicative m, MonadIO m) => Session m (Timed NominalDiffTime ())
+clockSession_ = clockSession <*> pure ()
 
 
--- | Runs the given wire continuously and prints its result to stderr.
--- Runs forever until an exception is raised.
---
--- The /printing interval/ sets the instants/printing ratio.  The higher
--- this value, the less often the output is printed.  Examples:  1000
--- means to print at every 1000-th instant, 1 means to print at every
--- instant.
+-- | State delta generator for a simple counting clock.  Denotes a fixed
+-- framerate.  This is likely more useful than 'clockSession' for
+-- simulations and real-time games.
 
-testWire ::
-    forall a b e m. (MonadIO m, Show e)
-    => Int                -- ^ Printing interval.
-    -> Int                -- ^ 'threadDelay' between instants.
-    -> m a                -- ^ Input generator.
-    -> Session m          -- ^ Initial session value.
-    -> Wire e m a String  -- ^ Wire to test.
-    -> m b
-testWire int delay getInput = loop 0
-    where
-    loop :: Int -> Session m -> Wire e m a String -> m b
-    loop n' s' w' = do
-        x' <- getInput
-        (mx, w, s) <- stepSession w' s' x'
-        n <- mx `seq` liftIO (testPrint n' int mx)
-        when (delay > 0) (liftIO (threadDelay delay))
-        loop n s w
+countSession ::
+    (Applicative m)
+    => t  -- ^ Increment size.
+    -> Session m (s -> Timed t s)
+countSession dt =
+    let loop = Session (pure (Timed dt, loop))
+    in loop
 
 
--- | Like 'testWire', but for pure wires.
+-- | Non-extending version of 'countSession'.
 
-testWireP ::
-    forall a b e m. (MonadIO m, Show e)
-    => Int                       -- ^ Printing interval.
-    -> Int                       -- ^ 'threadDelay' between instants.
-    -> m a                       -- ^ Input generator.
-    -> Session m                 -- ^ Initial session value.
-    -> Wire e Identity a String  -- ^ Wire to test.
-    -> m b
-testWireP int delay getInput = loop 0
-    where
-    loop :: Int -> Session m -> Wire e Identity a String -> m b
-    loop n' s' w' = do
-        x' <- getInput
-        (mx, w, s) <- stepSessionP w' s' x'
-        n <- mx `seq` liftIO (testPrint n' int mx)
-        when (delay > 0) (liftIO (threadDelay delay))
-        loop n s w
+countSession_ :: (Applicative m, MonadIO m) => t -> Session m (Timed t ())
+countSession_ dt = countSession dt <*> pure ()
diff --git a/Control/Wire/Switch.hs b/Control/Wire/Switch.hs
new file mode 100644
--- /dev/null
+++ b/Control/Wire/Switch.hs
@@ -0,0 +1,250 @@
+-- |
+-- Module:     Control.Wire.Switch
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Control.Wire.Switch
+    ( -- * Simple switching
+      (-->),
+
+      -- * Context switching
+      modes,
+
+      -- * Event-based switching
+      -- ** Intrinsic
+      switch,
+      dSwitch,
+      -- ** Intrinsic continuable
+      kSwitch,
+      dkSwitch,
+      -- ** Extrinsic
+      rSwitch,
+      drSwitch,
+      -- ** Extrinsic continuable
+      krSwitch,
+      dkrSwitch
+    )
+    where
+
+import qualified Data.Map as M
+import Control.Applicative
+import Control.Arrow
+import Control.Monad
+import Control.Wire.Core
+import Control.Wire.Event
+import Control.Wire.Unsafe.Event
+import Data.Monoid
+
+
+-- | Acts like the first wire until it inhibits, then switches to the
+-- second wire.  Infixr 1.
+--
+-- * Depends: like current wire.
+--
+-- * Inhibits: after switching like the second wire.
+--
+-- * Switch: now.
+
+(-->) :: (Monad m) => Wire s e m a b -> Wire s e m a b -> Wire s e m a b
+w1' --> w2' =
+    WGen $ \ds mx' -> do
+        (mx, w1) <- stepWire w1' ds mx'
+        case mx of
+          Left _ | Right _ <- mx' -> stepWire w2' ds mx'
+          _                       -> mx `seq` return (mx, w1 --> w2')
+
+infixr 1 -->
+
+
+-- | Intrinsic continuable switch:  Delayed version of 'kSwitch'.
+--
+-- * Inhibits: like the first argument wire, like the new wire after
+--   switch.  Inhibition of the second argument wire is ignored.
+--
+-- * Switch: once, after now, restart state.
+
+dkSwitch ::
+    (Monad m)
+    => Wire s e m a b
+    -> Wire s e m (a, b) (Event (Wire s e m a b -> Wire s e m a b))
+    -> Wire s e m a b
+dkSwitch w1' w2' =
+    WGen $ \ds mx' -> do
+        (mx,  w1) <- stepWire w1' ds mx'
+        (mev, w2) <- stepWire w2' ds (liftA2 (,) mx' mx)
+        let w | Right (Event sw) <- mev = sw w1
+              | otherwise = dkSwitch w1 w2
+        return (mx, w)
+
+
+-- | Extrinsic switch:  Delayed version of 'rSwitch'.
+--
+-- * Inhibits: like the current wire.
+--
+-- * Switch: recurrent, after now, restart state.
+
+drSwitch ::
+    (Monad m)
+    => Wire s e m a b
+    -> Wire s e m (a, Event (Wire s e m a b)) b
+drSwitch w' =
+    WGen $ \ds mx' ->
+        let nw w | Right (_, Event w1) <- mx' = w1
+                 | otherwise = w
+        in liftM (second (drSwitch . nw)) (stepWire w' ds (fmap fst mx'))
+
+
+-- | Intrinsic switch:  Delayed version of 'switch'.
+--
+-- * Inhibits: like argument wire until switch, then like the new wire.
+--
+-- * Switch: once, after now, restart state.
+
+dSwitch ::
+    (Monad m)
+    => Wire s e m a (b, Event (Wire s e m a b))
+    -> Wire s e m a b
+dSwitch w' =
+    WGen $ \ds mx' -> do
+        (mx, w) <- stepWire w' ds mx'
+        let nw | Right (_, Event w1) <- mx = w1
+               | otherwise = dSwitch w
+        return (fmap fst mx, nw)
+
+
+-- | Extrinsic continuable switch.  Delayed version of 'krSwitch'.
+--
+-- * Inhibits: like the current wire.
+--
+-- * Switch: recurrent, after now, restart state.
+
+dkrSwitch ::
+    (Monad m)
+    => Wire s e m a b
+    -> Wire s e m (a, Event (Wire s e m a b -> Wire s e m a b)) b
+dkrSwitch w' =
+    WGen $ \ds mx' ->
+        let nw w | Right (_, Event f) <- mx' = f w
+                 | otherwise = w
+        in liftM (second (dkrSwitch . nw)) (stepWire w' ds (fmap fst mx'))
+
+
+-- | Intrinsic continuable switch:  @kSwitch w1 w2@ starts with @w1@.
+-- Its signal is received by @w2@, which may choose to switch to a new
+-- wire.  Passes the wire we are switching away from to the new wire,
+-- such that it may be reused in it.
+--
+-- * Inhibits: like the first argument wire, like the new wire after
+--   switch.  Inhibition of the second argument wire is ignored.
+--
+-- * Switch: once, now, restart state.
+
+kSwitch ::
+    (Monad m, Monoid s)
+    => Wire s e m a b
+    -> Wire s e m (a, b) (Event (Wire s e m a b -> Wire s e m a b))
+    -> Wire s e m a b
+kSwitch w1' w2' =
+    WGen $ \ds mx' -> do
+        (mx,  w1) <- stepWire w1' ds mx'
+        (mev, w2) <- stepWire w2' ds (liftA2 (,) mx' mx)
+        case mev of
+          Right (Event sw) -> stepWire (sw w1) mempty mx'
+          _                -> return (mx, kSwitch w1 w2)
+
+
+-- | Extrinsic continuable switch.  This switch works like 'rSwitch',
+-- except that it passes the wire we are switching away from to the new
+-- wire.
+--
+-- * Inhibits: like the current wire.
+--
+-- * Switch: recurrent, now, restart state.
+
+krSwitch ::
+    (Monad m)
+    => Wire s e m a b
+    -> Wire s e m (a, Event (Wire s e m a b -> Wire s e m a b)) b
+krSwitch w'' =
+    WGen $ \ds mx' ->
+        let w' | Right (_, Event f) <- mx' = f w''
+               | otherwise = w''
+        in liftM (second krSwitch) (stepWire w' ds (fmap fst mx'))
+
+
+-- | Route the left input signal based on the current mode.  The right
+-- input signal can be used to change the current mode.  When switching
+-- away from a mode and then switching back to it, it will be resumed.
+-- Freezes time during inactivity.
+--
+-- * Complexity: O(n * log n) space, O(log n) lookup time on switch wrt
+--   number of started, inactive modes.
+--
+-- * Depends: like currently active wire (left), now (right).
+--
+-- * Inhibits: when active wire inhibits.
+--
+-- * Switch: now on mode change.
+
+modes ::
+    (Monad m, Ord k)
+    => k  -- ^ Initial mode.
+    -> (k -> Wire s e m a b)  -- ^ Select wire for given mode.
+    -> Wire s e m (a, Event k) b
+modes m0 select = loop M.empty m0 (select m0)
+    where
+    loop ms' m' w'' =
+        WGen $ \ds mxev' ->
+            case mxev' of
+              Left _ -> do
+                  (mx, w) <- stepWire w'' ds (fmap fst mxev')
+                  return (mx, loop ms' m' w)
+              Right (x', ev) -> do
+                  let (ms, m, w') = switch ms' m' w'' ev
+                  (mx, w) <- stepWire w' ds (Right x')
+                  return (mx, loop ms m w)
+
+    switch ms' m' w' NoEvent = (ms', m', w')
+    switch ms' m' w' (Event m) =
+        let ms = M.insert m' w' ms' in
+        case M.lookup m ms of
+          Nothing -> (ms, m, select m)
+          Just w  -> (M.delete m ms, m, w)
+
+
+-- | Extrinsic switch:  Start with the given wire.  Each time the input
+-- event occurs, switch to the wire it carries.
+--
+-- * Inhibits: like the current wire.
+--
+-- * Switch: recurrent, now, restart state.
+
+rSwitch ::
+    (Monad m)
+    => Wire s e m a b
+    -> Wire s e m (a, Event (Wire s e m a b)) b
+rSwitch w'' =
+    WGen $ \ds mx' ->
+        let w' | Right (_, Event w1) <- mx' = w1
+               | otherwise = w''
+        in liftM (second rSwitch) (stepWire w' ds (fmap fst mx'))
+
+
+-- | Intrinsic switch:  Start with the given wire.  As soon as its event
+-- occurs, switch to the wire in the event's value.
+--
+-- * Inhibits: like argument wire until switch, then like the new wire.
+--
+-- * Switch: once, now, restart state.
+
+switch ::
+    (Monad m, Monoid s)
+    => Wire s e m a (b, Event (Wire s e m a b))
+    -> Wire s e m a b
+switch w' =
+    WGen $ \ds mx' -> do
+        (mx, w) <- stepWire w' ds mx'
+        case mx of
+          Right (_, Event w1) -> stepWire w1 mempty mx'
+          _                   -> return (fmap fst mx, switch w)
diff --git a/Control/Wire/Time.hs b/Control/Wire/Time.hs
new file mode 100644
--- /dev/null
+++ b/Control/Wire/Time.hs
@@ -0,0 +1,38 @@
+-- |
+-- Module:     Control.Wire.Time
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Control.Wire.Time
+    ( -- * Time wires
+      time,
+      timeF,
+      timeFrom
+    )
+    where
+
+import Control.Wire.Core
+import Control.Wire.Session
+
+
+-- | Local time starting from zero.
+
+time :: (HasTime t s) => Wire s e m a t
+time = timeFrom 0
+
+
+-- | Local time starting from zero, converted to your favorite
+-- fractional type.
+
+timeF :: (Fractional b, HasTime t s, Monad m) => Wire s e m a b
+timeF = fmap realToFrac time
+
+
+-- | Local time starting from the given value.
+
+timeFrom :: (HasTime t s) => t -> Wire s e m a t
+timeFrom t' =
+    mkSF $ \ds _ ->
+        let t = t' + dtime ds
+        in t `seq` (t, timeFrom t)
diff --git a/Control/Wire/TimedMap.hs b/Control/Wire/TimedMap.hs
deleted file mode 100644
--- a/Control/Wire/TimedMap.hs
+++ /dev/null
@@ -1,118 +0,0 @@
--- |
--- Module:     Control.Wire.TimedMap
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Timed maps for efficient cleanups in the context wires.
-
-module Control.Wire.TimedMap
-    ( -- * Timed maps
-      TimedMap,
-      -- * Queries
-      findWithDefault,
-      lookup,
-      -- * Construction
-      empty,
-      -- * Insertion
-      insert,
-      -- * Deletion
-      cleanup,
-      cut,
-      delete
-    )
-    where
-
-import qualified Data.Map as M
-import qualified Data.Set as S
-import Control.Monad
-import Data.Data
-import Data.Map (Map)
-import Data.Set (Set)
-import Prelude hiding (lookup)
-
-
--- | A timed map is a map with an additional index based on time.
-
-data TimedMap t k a =
-    TimedMap !(Map k (a, t)) !(Map t (Set k))
-    deriving (Data, Show, Typeable)
-
-
--- | Remove all elements older than the given time.
-
-cleanup :: (Ord k, Ord t) => t -> TimedMap t k a -> TimedMap t k a
-cleanup t0 (TimedMap mk' mt') = TimedMap mk mt
-    where
-    (older', middle, mt) = M.splitLookup t0 mt'
-    older =
-        M.fromDistinctAscList .
-        map (, ()) .
-        S.toList .
-        M.foldl' S.union S.empty .
-        maybe id (M.insert t0) middle $ older'
-    mk = mk' M.\\ older
-
-
--- | Remove all but the given number of latest elements.
-
-cut :: (Ord k, Ord t) => Int -> TimedMap t k a -> TimedMap t k a
-cut n !tm@(TimedMap mk mt)
-    | M.size mk > n =
-        let k = S.findMin . snd . M.findMin $ mt in
-        cut n (delete k tm)
-    | otherwise = tm
-
-
--- | Deletes the given key from the timed map.
-
-delete :: (Ord k, Ord t) => k -> TimedMap t k a -> TimedMap t k a
-delete k (TimedMap mk' mt') = TimedMap mk mt
-    where
-    mk = M.delete k mk'
-    mt = case M.lookup k mk' of
-           Nothing     -> mt'
-           Just (_, t') ->
-               let alter Nothing = Nothing
-                   alter (Just s') = do
-                       let s = S.delete k s'
-                       guard (not (S.null s))
-                       return s
-               in M.alter alter t' mt'
-
-
--- | Like 'lookup', but with a default value, if the key is not in the
--- map.
-
-findWithDefault :: (Ord k) => (a, t) -> k -> TimedMap t k a -> (a, t)
-findWithDefault def k = maybe def id . lookup k
-
-
--- | Empty timed map.
-
-empty :: TimedMap t k a
-empty = TimedMap M.empty M.empty
-
-
--- | Insert into the timed map.
-
-insert :: (Ord k, Ord t) => t -> k -> a -> TimedMap t k a -> TimedMap t k a
-insert t k x (TimedMap mk' mt') = TimedMap mk mt
-    where
-    mk = M.insert k (x, t) mk'
-    mt = case M.lookup k mk' of
-           Nothing      -> M.insertWith S.union t (S.singleton k) mt'
-           Just (_, t') ->
-               let alter Nothing = Nothing
-                   alter (Just s') = do
-                       let s = S.delete k s'
-                       guard (not (S.null s))
-                       return s
-               in M.insertWith S.union t (S.singleton k) .
-                  M.alter alter t' $ mt'
-
-
--- | Look up the given key in the timed map.
-
-lookup :: (Ord k) => k -> TimedMap t k a -> Maybe (a, t)
-lookup k (TimedMap mk _) = M.lookup k mk
diff --git a/Control/Wire/Trans.hs b/Control/Wire/Trans.hs
deleted file mode 100644
--- a/Control/Wire/Trans.hs
+++ /dev/null
@@ -1,25 +0,0 @@
--- |
--- Module:     Control.Wire.Trans
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Proxy module to all wire combinator modules.
-
-module Control.Wire.Trans
-    ( -- * Reexports
-      module Control.Wire.Trans.Combine,
-      module Control.Wire.Trans.Embed,
-      module Control.Wire.Trans.Event,
-      module Control.Wire.Trans.Simple,
-      module Control.Wire.Trans.Switch,
-      module Control.Wire.Trans.Time
-    )
-    where
-
-import Control.Wire.Trans.Combine
-import Control.Wire.Trans.Embed
-import Control.Wire.Trans.Event
-import Control.Wire.Trans.Simple
-import Control.Wire.Trans.Switch
-import Control.Wire.Trans.Time
diff --git a/Control/Wire/Trans/Combine.hs b/Control/Wire/Trans/Combine.hs
deleted file mode 100644
--- a/Control/Wire/Trans/Combine.hs
+++ /dev/null
@@ -1,110 +0,0 @@
--- |
--- Module:     Control.Wire.Trans.Combine
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Wire combinators to manage sets of wires.
-
-module Control.Wire.Trans.Combine
-    ( -- * Multiplexing
-      context,
-      contextLatest,
-      contextLimit,
-
-      -- * Multicast
-      multicast
-    )
-    where
-
-import qualified Control.Wire.TimedMap as Tm
-import qualified Data.Map as M
-import qualified Data.Traversable as T
-import Control.Wire.TimedMap (TimedMap)
-import Control.Wire.Wire
-import Data.Map (Map)
-
-
--- | The argument function turns the input signal into a context.  For
--- each context the given base wire evolves individually.
---
--- Note: Incorrect usage can lead to a memory leak.  Consider using
--- 'contextLimit' instead.
---
--- * Complexity:  O(n) space, O(log n) time wrt to number of stored
--- contexts.
---
--- * Depends: current instant.
---
--- * Inhibits: when the context wire inhibits.
-
-context ::
-    forall a b m e k. (Monad m, Ord k)
-    => (a -> k)      -- ^ Function to turn the signal into a context.
-    -> Wire e m a b  -- ^ Base wire.
-    -> Wire e m a b
-context key w0 = context' M.empty 0
-    where
-    context' :: Map k (Wire e m a b, Time) -> Time -> Wire e m a b
-    context' !ctxs t' =
-        mkGen $ \dt' x' -> do
-            let ctx      = key x'
-                (w', t0) = M.findWithDefault (w0, t') ctx ctxs
-                t        = t' + dt'
-                dt       = t - t0
-            (mx, w) <- dt `seq` stepWire w' dt x'
-            return (mx, context' (M.insert ctx (w, t) ctxs) t)
-
-
--- | Same as 'context', but keeps only the latest given number of
--- contexts.
-
-contextLatest ::
-    (Monad m, Ord k)
-    => (a -> k)      -- ^ Signal to context.
-    -> Int           -- ^ Maximum number of latest wires.
-    -> Wire e m a b  -- ^ Base wire.
-    -> Wire e m a b
-contextLatest key maxWires = contextLimit key (\_ _ -> Tm.cut maxWires)
-
-
--- | Same as 'context', but applies the given cleanup function to the
--- context map at every instant.  This can be used to drop older wires.
-
-contextLimit ::
-    forall a b m e k. (Monad m, Ord k)
-    => (a -> k)      -- ^ Function to turn the signal into a context.
-    -> (forall w. Int -> Time -> TimedMap Time k w -> TimedMap Time k w)
-            -- ^ Cleanup function.  Receives the current instant number,
-            -- the current local time and the current map.
-    -> Wire e m a b  -- ^ Base wire.
-    -> Wire e m a b
-contextLimit key uf w0 = context' 0 Tm.empty 0
-    where
-    context' :: Int -> TimedMap Time k (Wire e m a b) -> Time -> Wire e m a b
-    context' !n !ctxs t' =
-        mkGen $ \dt' x' -> do
-            let ctx      = key x'
-                (w', t0) = Tm.findWithDefault (w0, t') ctx ctxs
-                t        = t' + dt'
-                dt       = t - t0
-            (mx, w) <- dt `seq` stepWire w' dt x'
-            return (mx, context' (n + 1) (uf n t (Tm.insert t ctx w ctxs)) t)
-
-
--- | Broadcast the input signal to all of the given wires collecting
--- their results.  Each of the given subwires is evolved individually.
---
--- * Depends: like the most dependent subwire.
---
--- * Inhibits: when any of the subwires inhibits.
-
-multicast ::
-    (Monad m, T.Traversable f)
-    => f (Wire e m a b)
-    -> Wire e m a (f b)
-multicast ws' =
-    mkGen $ \dt x' -> do
-        res <- T.mapM (\w -> stepWire w dt x') ws'
-        let resx = T.sequence . fmap (\(mx, w) -> fmap (, w) mx) $ res
-        return (fmap (fmap fst) resx, multicast (fmap snd res))
diff --git a/Control/Wire/Trans/Embed.hs b/Control/Wire/Trans/Embed.hs
deleted file mode 100644
--- a/Control/Wire/Trans/Embed.hs
+++ /dev/null
@@ -1,47 +0,0 @@
--- |
--- Module:     Control.Wire.Trans.Embed
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Combinators for embedding wires.
-
-module Control.Wire.Trans.Embed
-    ( -- * Embedding wires
-      embed
-    )
-    where
-
-import Control.Wire.Wire
-
-
--- | Performs the argument wire with the input time delta.  It is
--- stepped often enough to catch up with the main wire.  The individual
--- results are combined as given by the fold (second and third
--- argument).
---
--- * Complexity: O(n) time wrt stepping the subwire, where n is the
---   number of times the subwire is stepped.
---
--- * Depends: like argument wire, if stepped.
---
--- * Inhibits: When the fold results in a 'Left'.
-
-embed ::
-    (Monad m)
-    => (a -> Time)                -- ^ Time delta for the subwire.
-    -> (Either e c -> Either e b -> Either e c)  -- ^ Folding function.
-    -> Either e c                      -- ^ Fold base value.
-    -> Wire e m a b               -- ^ Subwire to step.
-    -> Wire e m a c
-embed delta fold z = embed' 0
-    where
-    embed' rdt w0 =
-        mkGen $ \dt x' ->
-            let idt = delta x'
-                loop odt r w'
-                    | odt >= idt = do
-                        (mx, w) <- stepWire w' idt x'
-                        loop (odt - idt) (fold r mx) w
-                    | otherwise = return (r, embed' odt w')
-            in loop (rdt + dt) z w0
diff --git a/Control/Wire/Trans/Event.hs b/Control/Wire/Trans/Event.hs
deleted file mode 100644
--- a/Control/Wire/Trans/Event.hs
+++ /dev/null
@@ -1,211 +0,0 @@
--- |
--- Module:     Control.Wire.Trans.Event
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Event-related wire combinators.
-
-module Control.Wire.Trans.Event
-    ( -- * Combinators
-      eitherE,
-      (<||>),
-
-      -- * Holding events
-      hold,
-      hold_,
-      holdFor,
-      holdForI,
-
-      -- * Inhibition
-      (<!>),
-      event,
-      exhibit,
-      gotEvent,
-      notE
-    )
-    where
-
-import Control.Arrow
-import Control.Category
-import Control.Wire.Types
-import Control.Wire.Wire
-import Data.Monoid hiding ((<>))
-import Data.Semigroup
-import Prelude hiding ((.), id)
-
-
--- | Try both wires combining their results with the given functions.
---
--- * Like argument wires.
---
--- * Inhibits: when both wires inhibit.
-
-eitherE ::
-    (Monad m, Monoid e)
-    => (b1 -> b)        -- ^ Only left.
-    -> (b2 -> b)        -- ^ Only right.
-    -> (b1 -> b2 -> b)  -- ^ Both.
-    -> Wire e m a b1   -- ^ First wire.
-    -> Wire e m a b2   -- ^ Second wire.
-    -> Wire e m a b
-eitherE left right both = eitherE'
-    where
-    eitherE' w1' w2' =
-        mkGen $ \dt x' -> do
-            (mx1, w1) <- stepWire w1' dt x'
-            (mx2, w2) <- stepWire w2' dt x'
-            let res =
-                    case (mx1, mx2) of
-                      (Left ex1, Left ex2) -> Left (mappend ex1 ex2)
-                      (Right x1, Right x2) -> Right (both x1 x2)
-                      (Right x1, _)        -> Right (left x1)
-                      (_, Right x2)        -> Right (right x2)
-            return (res, eitherE' w1 w2)
-
-
--- | Semigroup version of 'eitherE'.
-
-(<||>) ::
-    (Monad m, Monoid e, Semigroup b)
-    => Wire e m a b
-    -> Wire e m a b
-    -> Wire e m a b
-(<||>) = eitherE id id (<>)
-
-
--- | If the argument wire inhibits, inhibit with the given exception
--- instead.
---
--- * Depends: like argument wire.
---
--- * Inhibits: like argument wire.
-
-(<!>) :: (Monad m) => Wire e m a b -> e -> Wire e m a b
-w <!> ex = mapOutput (either (Left . const ex) Right) w
-
-
--- | Prevent a wire from inhibiting.  Instead produce a signal wrapped
--- in 'Maybe'.
---
--- Note:  You probably shouldn't use this function.
---
--- * Depends: like argument wire.
-
-event :: (Monad m) => Wire e m a b -> Wire e m a (Maybe b)
-event = mapOutput (Right . either (const Nothing) Just)
-
-
--- | Prevent a wire from inhibiting.  Instead produce the inhibition
--- value.
---
--- Note:  You probably shouldn't use this function.
---
--- * Depends: like argument wire.
-
-exhibit :: (Monad m) => Wire e m a b -> Wire e m a (Either e b)
-exhibit = mapOutput Right
-
-
--- | Prevent a wire from inhibiting.  Instead produce 'False', if the
--- wire inhibited.
---
--- Note:  You probably shouldn't use this function.
---
--- * Depends: like argument wire.
-
-gotEvent :: (Monad m) => Wire e m a b -> Wire e m a Bool
-gotEvent = mapOutput (Right . either (const False) (const True))
-
-
--- | Hold the latest event.  Produces the last produced value starting
--- with the given one.
---
--- * Depends: like argument wire.
-
-hold :: (Monad m) => b -> Wire e m a b -> Wire e m a b
-hold x0 w' =
-    mkGen $ \dt x' -> do
-        (mx, w) <- stepWire w' dt x'
-        case mx of
-          Left _  -> return (Right x0, hold x0 w)
-          Right x -> return (Right x, hold x w)
-
-
--- | Hold the event.  Once the argument wire produces the produced value
--- is held until the argument wire produces again.
---
--- * Depends: like argument wire.
---
--- * Inhibits: until the argument wire produces for the first time.
-
-hold_ :: (Monad m) => Wire e m a b -> Wire e m a b
-hold_ w' =
-    mkGen $ \dt x' -> do
-        (mx, w) <- stepWire w' dt x'
-        return (mx, either (const hold_) hold mx w)
-
-
--- | Hold the event for the given amount of time.  When the argument
--- wire produces, the produced value is kept for the given amount of
--- time.  If the wire produces again while another value is kept, the
--- new value takes precedence.
---
--- * Depends: like argument wire.
---
--- * Inhibits: as described.
-
-holdFor :: (Monad m) => Time -> Wire e m a b -> Wire e m a b
-holdFor t0 w = hold' . exhibit w
-    where
-    hold' =
-        mkPure $ \_ mx ->
-            case mx of
-              Left _  -> (mx, hold')
-              Right x -> (mx, hold'' t0 x)
-
-    hold'' t' x' =
-        mkPure $ \dt mx ->
-            let t = t' - dt in
-            case mx of
-              Left _
-                  | t > 0     -> (Right x', hold'' t x')
-                  | otherwise -> (mx, hold')
-              Right x -> (mx, hold'' t0 x)
-
-
--- | Hold the event for the given number of instances.  When the
--- argument wire produces, the produced value is kept for the given
--- number of instances.  If the wire produces again while another value
--- is kept, the new value takes precedence.
---
--- * Depends: like argument wire.
---
--- * Inhibits: as described.
-
-holdForI :: (Monad m) => Int -> Wire e m a b -> Wire e m a b
-holdForI t0 w = hold' . exhibit w
-    where
-    hold' = mkPure $ \_ -> id &&& either (const hold') (hold'' t0)
-
-    hold'' t x'
-        | t <= 0 = hold'
-        | otherwise =
-            mkPure $ \_ mx ->
-                case mx of
-                  Left _  -> (Right x', hold'' (t - 1) x')
-                  Right x -> (mx, hold'' t0 x)
-
-
--- | Act like the identity wire, if the argument wire inhibits.
--- Inhibit, if the argument wire produces.
---
--- * Depends: like argument wire.
---
--- * Inhibits: when argument wire produces.
-
-notE :: (Monad m, Monoid e) => Event e m a -> Event e m a
-notE w' =
-    mkGen $ \dt x' -> do
-        (mx, w) <- stepWire w' dt x'
-        return (either (const $ Right x') (const $ Left mempty) mx, notE w)
diff --git a/Control/Wire/Trans/Simple.hs b/Control/Wire/Trans/Simple.hs
deleted file mode 100644
--- a/Control/Wire/Trans/Simple.hs
+++ /dev/null
@@ -1,49 +0,0 @@
--- |
--- Module:     Control.Wire.Trans.Simple
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Basic wire combinators.
-
-module Control.Wire.Trans.Simple
-    ( -- * Predicate-based
-      ifW
-    )
-    where
-
-import Control.Arrow
-import Control.Monad
-import Control.Wire.Wire
-import Data.Monoid
-import Prelude hiding ((.), id)
-
-
--- | The wire @ifW p x y@ acts like @x@, when the predicate @p@ is true,
--- otherwise @y@.
---
--- * Complexity: like the predicate and the chosen wire.
---
--- * Depends: like the predicate and the chosen wire.
---
--- * Inhibits: when the predicate or the chosen wire inhibits.
-
-ifW ::
-    (Monad m, Monoid e)
-    => Wire e m a Bool  -- ^ Predicate.
-    -> Wire e m a b     -- ^ If true.
-    -> Wire e m a b     -- ^ If false.
-    -> Wire e m a b
-ifW = ifW' 0 0
-    where
-    ifW' !tx !ty wp' wx' wy' =
-        mkGen $ \dt x' -> do
-            (mb, wp) <- stepWire wp' dt x'
-            case mb of
-              Left ex -> return (Left ex, ifW' (tx + dt) (ty + dt) wp wx' wy')
-              Right b ->
-                  if b
-                    then liftM (second (\wx -> ifW' 0 (ty + dt) wp wx wy')) $
-                         stepWire wx' (tx + dt) x'
-                    else liftM (second (ifW' (tx + dt) 0 wp wx')) $
-                         stepWire wy' (ty + dt) x'
diff --git a/Control/Wire/Trans/Switch.hs b/Control/Wire/Trans/Switch.hs
deleted file mode 100644
--- a/Control/Wire/Trans/Switch.hs
+++ /dev/null
@@ -1,101 +0,0 @@
--- |
--- Module:     Control.Wire.Trans.Switch
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Switching combinators.  Notice that these combinators restart time
--- when switching.
-
-module Control.Wire.Trans.Switch
-    ( -- * Simple switching
-      andThen,
-      switch,
-      switchBy,
-      (-->)
-    )
-    where
-
-import Control.Arrow
-import Control.Monad
-import Control.Wire.Wire
-
-
--- | Infix variant of 'andThen'.
---
--- This operator is right-associative with precedence 1.
-
-(-->) :: (Monad m) => Wire e m a b -> Wire e m a b -> Wire e m a b
-(-->) = andThen
-
-infixr 1 -->
-
-
--- | Behaves like the first wire until it inhibits.  Switches to the
--- second wire as soon as the first one inhibits.
---
--- The @`andThen`@ operator is right-associative with precedence 1.
---
--- * Depends: like currently active wire.
---
--- * Inhibits: when switched to second wire and that one inhibits.
---
--- * Time: switching restarts time.
-
-andThen ::
-    (Monad m)
-    => Wire e m a b  -- ^ Wire to start with.
-    -> Wire e m a b  -- ^ Wire to switch into.
-    -> Wire e m a b
-andThen w1' w2' =
-    mkGen $ \dt x' -> do
-        (mx, w1) <- stepWire w1' dt x'
-        case mx of
-          Left _  -> stepWire w2' dt x'
-          Right _ -> return (mx, andThen w1 w2')
-
-infixr 1 `andThen`
-
-
--- | If the first argument wire produces a wire, switch to it
--- immediately.  If not, evolve the current wire.  The second argument
--- wire is the initial wire.
---
--- * Depends: like event wire and the currently active wire.
---
--- * Inhibits: when the currently active wire inhibits.
---
--- * Time: switching restarts time.
-
-switch ::
-    (Monad m)
-    => Wire e m a (Wire e m a b)  -- ^ Produces a wire to switch into.
-    -> Wire e m a b               -- ^ Initial wire.
-    -> Wire e m a b
-switch wnew' w0 =
-    mkGen $ \dt x' -> do
-        (w', wnew) <- liftM (first (either (const w0) id)) (stepWire wnew' dt x')
-        (mx, w) <- stepWire w' dt x'
-        return (mx, switch wnew w)
-
-
--- | Whenever the given wire inhibits, a new wire is constructed using
--- the given function.
---
--- * Depends: like currently active wire.
---
--- * Time: switching restarts time.
-
-switchBy ::
-    (Monad m)
-    => (e' -> Wire e' m a b)  -- ^ Wire selection function.
-    -> Wire e' m a b          -- ^ Initial wire.
-    -> Wire e m a b
-switchBy new w0 =
-    mkGen $ \dt x' ->
-        let select w' = do
-                (mx, w) <- stepWire w' dt x'
-                case mx of
-                  Left ex -> select (new ex)
-                  Right x -> return (Right x, switchBy new w)
-        in select w0
diff --git a/Control/Wire/Trans/Time.hs b/Control/Wire/Trans/Time.hs
deleted file mode 100644
--- a/Control/Wire/Trans/Time.hs
+++ /dev/null
@@ -1,31 +0,0 @@
--- |
--- Module:     Control.Wire.Trans.Time
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Time-related wire combinators.
-
-module Control.Wire.Trans.Time
-    ( -- * Local time
-      mapTime
-    )
-    where
-
-import Control.Arrow
-import Control.Monad
-import Control.Wire.Wire
-
-
--- | Maps the given function over the time deltas for the given wire.
---
--- * Complexity: like argument wire.
---
--- * Depends: like argument wire.
---
--- * Inhibits: like argument wire.
-
-mapTime :: (Monad m) => (Time -> Time) -> Wire e m a b -> Wire e m a b
-mapTime f w' =
-    mkGen $ \dt ->
-        liftM (second (mapTime f)) . stepWire w' (f dt)
diff --git a/Control/Wire/Types.hs b/Control/Wire/Types.hs
deleted file mode 100644
--- a/Control/Wire/Types.hs
+++ /dev/null
@@ -1,161 +0,0 @@
--- |
--- Module:     Control.Wire.Types
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Types used in Netwire.  Most notably this module implements the
--- instances for the various reactive classes.
-
-module Control.Wire.Types
-    ( -- * Convenient type aliases
-      LastException,
-      -- ** Events
-      Event,
-      EventM,
-      EventP,
-      -- ** Wires
-      WireM,
-      WireP,
-
-      -- * Type-related utilities
-      as,
-      inAs,
-      inLike,
-      like,
-      outAs,
-      outLike,
-      -- ** Predefined proxies
-      pDouble,
-      pFloat,
-      pInt,
-      pInteger,
-      pString
-    )
-    where
-
-import Control.Category
-import Control.Exception (SomeException)
-import Control.Monad
-import Control.Monad.Identity
-import Control.Wire.Wire
-import Data.Monoid
-import Data.Proxy
-import Prelude hiding ((.), id)
-
-
--- | Event wires are wires that act like identity wires, but may inhibit
--- depending on whether a certain event has occurred.
-
-type Event e m a = Wire e m a a
-
-
--- | 'WireP' equivalent of 'Event'.
-
-type EventP a = WireP a a
-
-
--- | 'WireM' equivalent of 'Event'.
-
-type EventM m a = WireM m a a
-
-
--- | Monoid for the last occurred exception.
-
-type LastException = Last SomeException
-
-
--- | Monadic wires using 'LastException' as the inhibition monoid.
-
-type WireM = Wire LastException
-
-
--- | Pure wires using 'LastException' as the inhibition monoid.
-
-type WireP = WireM Identity
-
-
--- | Type-restricted identity wire.  This is useful to specify the type
--- of a signal.
---
--- * Depends: current instant.
-
-as :: (Monad m) => Proxy a -> Wire e m a a
-as _ = id
-
-
--- | Utility to specify the input type of a wire.  The argument is
--- ignored.  For types with defaulting you might prefer 'inLike'.
---
--- > inAs (Proxy :: Proxy Double) highPeak
-
-inAs :: Proxy a -> w a b -> w a b
-inAs = const id
-
-
--- | Utility to specify the input type of a wire.  The first argument is
--- ignored.  This is useful to make use of defaulting or when writing a
--- dummy value is actually shorter.
---
--- > inLike (0 :: Double) highPeak
-
-inLike :: a -> w a b -> w a b
-inLike = const id
-
-
--- | Type-restricted identity wire.  This is useful to specify the type
--- of a signal.  The argument is ignored.
---
--- * Depends: current instant.
-
-like :: (Monad m) => a -> Wire e m a a
-like = const id
-
-
--- | Utility to specify the output type of a wire.  The argument is
--- ignored.  For types with defaulting you might prefer 'outLike'.
---
--- > outAs (Proxy :: Proxy Double) noiseM
-
-outAs :: Proxy b -> w a b -> w a b
-outAs = const id
-
-
--- | Utility to specify the output type of a wire.  The first argument
--- is ignored.  This is useful to make use of defaulting or when writing
--- a dummy value is actually shorter.
---
--- > outLike (0 :: Double) noiseM
-
-outLike :: b -> w a b -> w a b
-outLike = const id
-
-
--- | 'Double' proxy for use with 'inAs' or 'outAs'.
-
-pDouble :: Proxy Double
-pDouble = Proxy
-
-
--- | 'Float' proxy for use with 'inAs' or 'outAs'.
-
-pFloat :: Proxy Float
-pFloat = Proxy
-
-
--- | 'Int' proxy for use with 'inAs' or 'outAs'.
-
-pInt :: Proxy Int
-pInt = Proxy
-
-
--- | 'Integer' proxy for use with 'inAs' or 'outAs'.
-
-pInteger :: Proxy Integer
-pInteger = Proxy
-
-
--- | 'String' proxy for use with 'inAs' or 'outAs'.
-
-pString :: Proxy String
-pString = Proxy
diff --git a/Control/Wire/Unsafe/Event.hs b/Control/Wire/Unsafe/Event.hs
new file mode 100644
--- /dev/null
+++ b/Control/Wire/Unsafe/Event.hs
@@ -0,0 +1,78 @@
+-- |
+-- Module:     Control.Wire.Unsafe.Event
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Control.Wire.Unsafe.Event
+    ( -- * Events
+      Event(..),
+
+      -- * Helper functions
+      event,
+      merge,
+      occurred,
+      onEventM
+    )
+    where
+
+import Control.DeepSeq
+import Control.Monad
+import Control.Wire.Core
+import Data.Semigroup
+import Data.Typeable
+
+
+-- | Denotes a stream of values, each together with time of occurrence.
+-- Since 'Event' is commonly used for functional reactive programming it
+-- does not define most of the usual instances to protect continuous
+-- time and discrete event occurrence semantics.
+
+data Event a = Event a | NoEvent  deriving (Typeable)
+
+instance Functor Event where
+    fmap f = event NoEvent (Event . f)
+
+instance (Semigroup a) => Monoid (Event a) where
+    mempty = NoEvent
+    mappend = (<>)
+
+instance (NFData a) => NFData (Event a) where
+    rnf (Event x) = rnf x
+    rnf NoEvent   = ()
+
+instance (Semigroup a) => Semigroup (Event a) where
+    (<>) = merge (<>)
+
+
+-- | Fold the given event.
+
+event :: b -> (a -> b) -> Event a -> b
+event _ j (Event x) = j x
+event n _ NoEvent   = n
+
+
+-- | Merge two events using the given function when both occur at the
+-- same time.
+
+merge :: (a -> a -> a) -> Event a -> Event a -> Event a
+merge _ NoEvent NoEvent     = NoEvent
+merge _ (Event x) NoEvent   = Event x
+merge _ NoEvent (Event y)   = Event y
+merge f (Event x) (Event y) = Event (f x y)
+
+
+-- | Did the given event occur?
+
+occurred :: Event a -> Bool
+occurred = event False (const True)
+
+
+-- | Each time the given event occurs, perform the given action with the
+-- value the event carries.  The resulting event carries the result of
+-- the action.
+--
+-- * Depends: now.
+
+onEventM :: (Monad m) => (a -> m b) -> Wire s e m (Event a) (Event b)
+onEventM c = mkGen_ $ liftM Right . event (return NoEvent) (liftM Event . c)
diff --git a/Control/Wire/Wire.hs b/Control/Wire/Wire.hs
deleted file mode 100644
--- a/Control/Wire/Wire.hs
+++ /dev/null
@@ -1,376 +0,0 @@
--- |
--- Module:     Control.Wire.Wire
--- Copyright:  (c) 2012 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- This is the core module implementing the 'Wire' type.
-
-module Control.Wire.Wire
-    ( -- * Wires
-      Wire(..),
-      Time,
-      -- ** Constructing wires
-      mkFix,
-      mkFixM,
-      mkGen,
-      mkPure,
-      mkState,
-      mkStateM,
-      -- ** Simple predefined wires
-      constant,
-      identity,
-      never,
-      -- ** Simple predefined combinators
-      cons,
-      fixW,
-      mapOutput,
-
-      -- * Stepping
-      stepWire,
-      stepWireP
-    )
-    where
-
-import qualified Data.Bifunctor as Bi
-import Control.Applicative
-import Control.Arrow
-import Control.Category
-import Control.Monad
-import Control.Monad.Fix
-import Control.Monad.Identity
-import Data.AdditiveGroup
-import Data.AffineSpace
-import Data.Cross
-import Data.Monoid
-import Data.Profunctor
-import Data.String
-import Data.VectorSpace
-import Prelude hiding ((.), id)
-
-
--- | Time.
-
-type Time = Double
-
-
--- | A wire is a signal function from an input value of type @a@ that
--- either /produces/ an output value of type @b@ or /inhibits/ with a
--- value of type @e@.  The underlying monad is @m@.
-
-data Wire e m a b
-    = WGen (Time -> a -> m (Either e b, Wire e m a b))
-    | WPure (Time -> a -> (Either e b, Wire e m a b))
-
-instance (AdditiveGroup b, Monad m) => AdditiveGroup (Wire e m a b) where
-    zeroV = pure zeroV
-    (^+^) = liftA2 (^+^)
-    negateV = fmap negateV
-
-instance (AdditiveGroup (Diff b), AffineSpace b, Monad m) => AffineSpace (Wire e m a b) where
-    type Diff (Wire e m a b) = Wire e m a (Diff b)
-    (.-.) = liftA2 (.-.)
-    (.+^) = liftA2 (.+^)
-
-instance (Monad m, Monoid e) => Alternative (Wire e m a) where
-    empty = mkFix (const . const $ Left mempty)
-
-    (<|>) = loop 0
-        where
-        loop !t2 (WPure f1) w2'@(WPure f2) =
-            mkPure $ \dt x' ->
-                let (mx1, w1) = f1 dt x' in
-                case mx1 of
-                  Left ex1 ->
-                      let (mx2, w2) = f2 (t2 + dt) x' in
-                      (Bi.first (mappend ex1) mx2, loop 0 w1 w2)
-                  Right _ -> (mx1, loop (t2 + dt) w1 w2')
-
-        loop !t2 w1' w2' =
-            mkGen $ \dt x' -> do
-                (mx1, w1) <- stepWire w1' dt x'
-                case mx1 of
-                  Left ex1 -> do
-                      (mx2, w2) <- stepWire w2' (t2 + dt) x'
-                      return (Bi.first (mappend ex1) mx2, loop 0 w1 w2)
-                  Right _ -> return (mx1, loop (t2 + dt) w1 w2')
-
-instance (Monad m) => Applicative (Wire e m a) where
-    pure = constant
-
-    (<*>) = loop 0
-        where
-        loop !tx (WPure ff) wx'@(WPure fx) =
-            mkPure $ \dt x' ->
-                let (mf, wf) = ff dt x' in
-                case mf of
-                  Right f ->
-                      let (mx, wx) = fx (tx + dt) x' in
-                      (fmap f mx, loop 0 wf wx)
-                  Left ex -> (Left ex, loop (tx + dt) wf wx')
-
-        loop !tx wf' wx' =
-            mkGen $ \dt x' -> do
-                (mf, wf) <- stepWire wf' dt x'
-                case mf of
-                  Right f -> do
-                      (mx, wx) <- stepWire wx' (tx + dt) x'
-                      return (fmap f mx, loop 0 wf wx)
-                  Left ex -> return (Left ex, loop (tx + dt) wf wx')
-
-instance (Monad m) => Arrow (Wire e m) where
-    arr f     = mkFix (const $ Right . f)
-    first w   = liftA2 (,) (lmap fst w) (arr snd)
-    second w  = liftA2 (,) (arr fst) (lmap snd w)
-    (&&&)     = liftA2 (,)
-    w1 *** w2 = liftA2 (,) (lmap fst w1) (lmap snd w2)
-
-instance (Monad m) => ArrowChoice (Wire e m) where
-    (|||) = loop 0 0
-        where
-        loop !tl !tr wl' wr' =
-            mkGen $ \dt ->
-                either (\x' -> do
-                            (mx, wl) <- stepWire wl' (tl + dt) x'
-                            return (mx, loop 0 (tr + dt) wl wr'))
-                       (\x' -> do
-                            (mx, wr) <- stepWire wr' (tr + dt) x'
-                            return (mx, loop (tl + dt) 0 wl' wr))
-
-    w1 +++ w2 = fmap Left w1 ||| fmap Right w2
-
-    left = loop 0
-        where
-        loop !tl wl' =
-            mkGen $ \dt ->
-                either (liftM (fmap Left *** loop 0) . stepWire wl' (tl + dt))
-                       (\x -> return (Right (Right x), loop (tl + dt) wl'))
-
-    right = loop 0
-        where
-        loop !tr wr' =
-            mkGen $ \dt ->
-                either (\x -> return (Right (Left x), loop (tr + dt) wr'))
-                       (liftM (fmap Right *** loop 0) . stepWire wr' (tr + dt))
-
-instance (MonadFix m) => ArrowLoop (Wire e m) where
-    loop w' =
-        mkGen $ \dt x' ->
-            liftM (fmap fst *** loop) .
-            mfix $ \ ~(mx, _) ->
-                let feedbackErr = error "Feedback loop broken by inhibition" in
-                stepWire w' dt (x', either (const feedbackErr) snd mx)
-
-instance (Monad m, Monoid e) => ArrowPlus (Wire e m) where
-    (<+>) = (<|>)
-
-instance (Monad m, Monoid e) => ArrowZero (Wire e m) where
-    zeroArrow = empty
-
-instance (Monad m) => Category (Wire e m) where
-    id = identity
-
-    (.) = loop 0
-        where
-        loop !t2 w2'@(WPure f2) (WPure f1) =
-            mkPure $ \dt x'' ->
-                let (mx', w1) = f1 dt x'' in
-                case mx' of
-                  Right x' ->
-                      let (mx, w2) = f2 (t2 + dt) x' in
-                      (mx, loop 0 w2 w1)
-                  Left ex -> (Left ex, loop (t2 + dt) w2' w1)
-
-        loop !t2 w2' w1' =
-            mkGen $ \dt x'' -> do
-                (mx', w1) <- stepWire w1' dt x''
-                case mx' of
-                  Right x' -> do
-                      (mx, w2) <- stepWire w2' (t2 + dt) x'
-                      return (mx, loop 0 w2 w1)
-                  Left ex -> return (Left ex, loop (t2 + dt) w2' w1)
-
-instance (Floating b, Monad m) => Floating (Wire e m a b) where
-    pi = pure pi
-    sqrt = fmap sqrt
-
-    (**) = liftA2 (**)
-    exp = fmap exp
-    log = fmap log
-    logBase = liftA2 logBase
-
-    cos  = fmap cos;  sin  = fmap sin;  tan  = fmap tan
-    acos = fmap acos; asin = fmap asin; atan = fmap atan
-
-    cosh  = fmap cosh;  sinh  = fmap sinh;  tanh  = fmap tanh
-    acosh = fmap acosh; asinh = fmap asinh; atanh = fmap atanh
-
-instance (Fractional b, Monad m) => Fractional (Wire e m a b) where
-    (/) = liftA2 (/)
-    fromRational = pure . fromRational
-    recip = fmap recip
-
-instance (Monad m) => Functor (Wire e m a) where
-    fmap = mapOutput . fmap
-
-instance (HasCross2 b, Monad m) => HasCross2 (Wire e m a b) where
-    cross2 = fmap cross2
-
-instance (HasCross3 b, Monad m) => HasCross3 (Wire e m a b) where
-    cross3 = liftA2 cross3
-
-instance (HasNormal b, Monad m) => HasNormal (Wire e m a b) where
-    normalVec = fmap normalVec
-
-instance (InnerSpace b, Monad m) => InnerSpace (Wire e m a b) where
-    (<.>) = liftA2 (<.>)
-
-instance (Monad m, Num b) => Num (Wire e m a b) where
-    (+) = liftA2 (+)
-    (-) = liftA2 (-)
-    (*) = liftA2 (*)
-
-    abs = fmap abs
-    signum = fmap signum
-    fromInteger = pure . fromInteger
-
-instance (IsString b, Monad m) => IsString (Wire e m a b) where
-    fromString = pure . fromString
-
-instance (Monad m, Monoid b) => Monoid (Wire e m a b) where
-    mempty  = pure mempty
-    mappend = liftA2 mappend
-
-instance (Monad m) => Profunctor (Wire e m) where
-    lmap f (WPure g) = WPure (\dt -> second (lmap f) . g dt . f)
-    lmap f (WGen g)  = WGen  (\dt -> liftM (second (lmap f)) . g dt . f)
-
-    rmap = fmap
-
-instance (Monad m, Read b) => Read (Wire e m a b) where
-    readsPrec n = map (first pure) . readsPrec n
-
-instance (Monad m, VectorSpace b) => VectorSpace (Wire e m a b) where
-    type Scalar (Wire e m a b) = Wire e m a (Scalar b)
-    (*^) = liftA2 (*^)
-
-
--- | Wire cons.  Prepend the given value to the wire's output stream.
--- This function is infixr like (':').
---
--- * Depends: like argument wire after the first instant.
---
--- * Inhibits: like argument wire after the first instant.
-
-cons :: b -> Wire e m a b -> Wire e m a b
-cons x xs = mkPure (\_ _ -> (Right x, xs))
-
-infixr 5 `cons`
-
-
--- | Variant of 'pure' without the 'Monad' constraint.  Using 'pure' is
--- preferable.
-
-constant :: b -> Wire e m a b
-constant = mkFix . const . const . Right
-
-
--- | Convenience combinator for the common case of feedback where you
--- ignore the input and produce the feedback value itself with 'loop'.
---
--- * Depends: like looped argument wire.
---
--- * Inhibits: when argument wire inhibits.
-
-fixW :: (MonadFix m) => Wire e m b b -> Wire e m a b
-fixW = loop . fmap (\x -> (x, x)) . lmap snd
-
-
--- | Variant of 'id' without the 'Monad' constraint.  Using 'id' is
--- preferable.
---
--- * Depends: current instant.
-
-identity :: Wire e m a a
-identity = WPure (\_ x -> (Right x, identity))
-
-
--- | Map the given function over the raw wire output.
-
-mapOutput :: (Monad m) => (Either e b' -> Either e b) -> Wire e m a b' -> Wire e m a b
-mapOutput f (WGen g)  = WGen  (\dt -> liftM (f *** mapOutput f) . g dt)
-mapOutput f (WPure g) = WPure (\dt -> (f *** mapOutput f) . g dt)
-
-
--- | Construct a pure stateless wire from the given function.
-
-mkFix :: (Time -> a -> Either e b) -> Wire e m a b
-mkFix f = let w = mkPure (\dt -> (, w) . f dt) in w
-
-
--- | Construct a stateless effectful wire from the given function.
-
-mkFixM :: (Monad m) => (Time -> a -> m (Either e b)) -> Wire e m a b
-mkFixM f = let w = mkGen (\dt -> liftM (, w) . f dt) in w
-
-
--- | Construct an effectful wire from the given function.
-
-mkGen :: (Time -> a -> m (Either e b, Wire e m a b)) -> Wire e m a b
-mkGen = WGen
-
-
--- | Construct a pure wire from the given function.
-
-mkPure :: (Time -> a -> (Either e b, Wire e m a b)) -> Wire e m a b
-mkPure = WPure
-
-
--- | Construct a pure wire from the given local state transision
--- function.
-
-mkState ::
-    s
-    -> (Time -> (a, s) -> (Either e b, s))
-    -> Wire e m a b
-mkState s0 f = loop s0
-    where
-    loop s' =
-        mkPure $ \dt x' ->
-            let (mx, s) = f dt (x', s') in
-            (mx, loop s)
-
-
--- | Construct a monadic wire from the given local state transision
--- function.
-
-mkStateM ::
-    (Monad m)
-    => s
-    -> (Time -> (a, s) -> m (Either e b, s))
-    -> Wire e m a b
-mkStateM s0 f = loop s0
-    where
-    loop s' =
-        mkGen $ \dt x' -> liftM (second loop) (f dt (x', s'))
-
-
--- | Variant of 'empty' without the 'Monad' constraint.  Using 'empty'
--- is preferable.
-
-never :: (Monoid e) => Wire e m a b
-never = mkFix . const . const $ Left mempty
-
-
--- | Perform an instant of the given wire.
-
-stepWire :: (Monad m) => Wire e m a b -> Time -> a -> m (Either e b, Wire e m a b)
-stepWire (WGen f)  dt = f dt
-stepWire (WPure f) dt = return . f dt
-
-
--- | Perform an instant of the given pure wire.
-
-stepWireP :: Wire e Identity a b -> Time -> a -> (Either e b, Wire e Identity a b)
-stepWireP (WGen f)  dt = runIdentity . f dt
-stepWireP (WPure f) dt = f dt
diff --git a/FRP/Netwire.hs b/FRP/Netwire.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Netwire.hs
@@ -0,0 +1,46 @@
+-- |
+-- Module:     FRP.Netwire
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module FRP.Netwire
+    ( -- * Netwire reexports
+      Wire,
+      WireP,
+      SimpleWire,
+      delay, evalWith, force, forceNF,
+      module Control.Wire.Event,
+      module Control.Wire.Interval,
+      module Control.Wire.Run,
+      module Control.Wire.Session,
+      module Control.Wire.Switch,
+      module Control.Wire.Time,
+
+      -- * Additional wires
+      module FRP.Netwire.Analyze,
+      module FRP.Netwire.Move,
+      module FRP.Netwire.Noise,
+
+      -- * External
+      module Control.Applicative,
+      module Control.Arrow,
+      module Control.Category,
+      module Data.Semigroup
+    )
+    where
+
+import Control.Applicative
+import Control.Arrow
+import Control.Category
+import Control.Wire
+import Control.Wire.Event
+import Control.Wire.Interval
+import Control.Wire.Run
+import Control.Wire.Session
+import Control.Wire.Switch
+import Control.Wire.Time
+import Data.Semigroup
+import FRP.Netwire.Analyze
+import FRP.Netwire.Move
+import FRP.Netwire.Noise
diff --git a/FRP/Netwire/Analyze.hs b/FRP/Netwire/Analyze.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Netwire/Analyze.hs
@@ -0,0 +1,310 @@
+-- |
+-- Module:     FRP.Netwire.Analyze
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module FRP.Netwire.Analyze
+    ( -- * Linear graphs
+      lAvg,
+      lGraph,
+      lGraphN,
+
+      -- * Staircase graphs
+      sAvg,
+      sGraph,
+      sGraphN,
+
+      -- * Peaks
+      highPeak,
+      highPeakBy,
+      lowPeak,
+      lowPeakBy,
+
+      -- * Debug
+      avgFps,
+      framerate
+    )
+    where
+
+import qualified FRP.Netwire.Utils.Timeline as Tl
+import qualified Data.Foldable as F
+import qualified Data.Sequence as Seq
+import Control.Wire
+import Prelude hiding ((.), id)
+
+
+-- | Average framerate over the last given number of samples.  One
+-- important thing to note is that the value of this wire will generally
+-- disagree with 'sAvg' composed with 'framerate'.  This is expected,
+-- because this wire simply calculates the arithmetic mean, whereas
+-- 'sAvg' will actually integrate the framerate graph.
+--
+-- Note:  This wire is for debugging purposes only, because it exposes
+-- discrete time.  Do not taint your application with discrete time.
+--
+-- * Complexity: O(n) time and space wrt number of samples.
+
+avgFps ::
+    (RealFloat b, HasTime t s)
+    => Int  -- ^ Number of samples.
+    -> Wire s e m a b
+avgFps int | int < 1 = error "avgFps: Non-positive number of samples"
+avgFps int = loop Seq.empty
+    where
+    intf = fromIntegral int
+    afps = (/ intf) . F.foldl' (+) 0
+
+    loop ss' =
+        mkSF $ \ds _ ->
+            let fps = recip . realToFrac . dtime $ ds
+                ss  = Seq.take int (fps Seq.<| ss')
+            in if isInfinite fps
+                 then (afps ss', loop ss')
+                 else ss `seq` (afps ss, loop ss)
+
+
+-- | Current framerate.
+--
+-- Note:  This wire is for debugging purposes only, because it exposes
+-- discrete time.  Do not taint your application with discrete time.
+--
+-- * Inhibits: when the clock stopped ticking.
+
+framerate ::
+    (Eq b, Fractional b, HasTime t s, Monoid e)
+    => Wire s e m a b
+framerate =
+    mkPure $ \ds _ ->
+        let dt = realToFrac (dtime ds)
+        in (if dt == 0 then Left mempty else Right (recip dt), framerate)
+
+
+-- | High peak.
+--
+-- * Depends: now.
+
+highPeak :: (Ord a) => Wire s e m a a
+highPeak = highPeakBy compare
+
+
+-- | High peak with respect to the given comparison function.
+--
+-- * Depends: now.
+
+highPeakBy :: (a -> a -> Ordering) -> Wire s e m a a
+highPeakBy = peakBy GT
+
+
+-- | Calculate the average of the signal over the given interval (from
+-- now).  This is done by calculating the integral of the corresponding
+-- linearly interpolated graph and dividing it by the interval length.
+-- See 'Tl.linAvg' for details.
+--
+-- Linear interpolation can be slow.  If you don't need it, you can use
+-- the staircase variant 'sAvg'.
+--
+-- Example: @lAvg 2@
+--
+-- * Complexity: O(s) space, O(s) time wrt number of samples in the
+--   interval.
+--
+-- * Depends: now.
+
+lAvg ::
+    (Fractional a, Fractional t, HasTime t s)
+    => t    -- ^ Interval size.
+    -> Wire s e m a a
+lAvg int =
+    mkSF $ \ds x ->
+        let t = dtime ds in
+        (x, loop t (Tl.singleton t x))
+
+    where
+    loop t' tl' =
+        mkSF $ \ds x ->
+            let t  = t' + dtime ds
+                t0 = t - int
+                tl = Tl.linCutL t0 (Tl.insert t x tl')
+                a  = Tl.linAvg t0 t tl
+            in (a, loop t tl)
+
+
+-- | Produce a linearly interpolated graph for the given points in time,
+-- where the magnitudes of the points are distances from /now/.
+--
+-- Linear interpolation can be slow.  If you don't need it, you can use
+-- the faster staircase variant 'sGraph'.
+--
+-- Example: @lGraph [0, 1, 2]@ will output the interpolated inputs at
+-- /now/, one second before now and two seconds before now.
+--
+-- * Complexity: O(s) space, O(n * log s) time, where s = number of
+--   samples in the interval, n = number of requested data points.
+--
+-- * Depends: now.
+
+lGraph ::
+    (Fractional a, Fractional t, HasTime t s)
+    => [t]  -- ^ Data points to produce.
+    -> Wire s e m a [a]
+lGraph qts =
+    mkSF $ \ds x ->
+        let t = dtime ds in
+        (x <$ qts, loop t (Tl.singleton t x))
+
+    where
+    earliest = maximum (map abs qts)
+
+    loop t' tl' =
+        mkSF $ \ds x ->
+            let t  = t' + dtime ds
+                tl = Tl.linCutL (t - earliest) (Tl.insert t x tl')
+                ps = map (\qt -> Tl.linLookup (t - abs qt) tl) qts
+            in (ps, loop t tl)
+
+
+-- | Graph the given interval from now with the given number of evenly
+-- distributed points in time.  Convenience interface to 'lGraph'.
+--
+-- Linear interpolation can be slow.  If you don't need it, you can use
+-- the faster staircase variant 'sGraphN'.
+--
+-- * Complexity: O(s) space, O(n * log s) time, where s = number of
+--   samples in the interval, n = number of requested data points.
+--
+-- * Depends: now.
+
+lGraphN ::
+    (Fractional a, Fractional t, HasTime t s)
+    => t    -- ^ Interval to graph from now.
+    -> Int  -- ^ Number of data points to produce.
+    -> Wire s e m a [a]
+lGraphN int n
+    | int <= 0 = error "lGraphN: Non-positive interval"
+    | n <= 0   = error "lGraphN: Non-positive number of data points"
+lGraphN int n =
+    let n1   = n - 1
+        f qt = realToFrac int * fromIntegral qt / fromIntegral n1
+    in lGraph (map f [0..n1])
+
+
+-- | Low peak.
+--
+-- * Depends: now.
+
+lowPeak :: (Ord a) => Wire s e m a a
+lowPeak = lowPeakBy compare
+
+
+-- | Low peak with respect to the given comparison function.
+--
+-- * Depends: now.
+
+lowPeakBy :: (a -> a -> Ordering) -> Wire s e m a a
+lowPeakBy = peakBy LT
+
+
+-- | Given peak with respect to the given comparison function.
+
+peakBy ::
+    (Eq o)
+    => o  -- ^ This ordering means the first argument is larger.
+    -> (a -> a -> o)  -- ^ Compare two elements.
+    -> Wire s e m a a
+peakBy o comp = mkSFN $ \x -> (x, loop x)
+    where
+    loop x' =
+        mkSFN $ \x ->
+            id &&& loop $
+            if comp x x' == o then x else x'
+
+
+-- | Calculate the average of the signal over the given interval (from
+-- now).  This is done by calculating the integral of the corresponding
+-- staircase graph and dividing it by the interval length.  See
+-- 'Tl.scAvg' for details.
+--
+-- See also 'lAvg'.
+--
+-- Example: @sAvg 2@
+--
+-- * Complexity: O(s) space, O(s) time wrt number of samples in the
+--   interval.
+--
+-- * Depends: now.
+
+sAvg ::
+    (Fractional a, Fractional t, HasTime t s)
+    => t    -- ^ Interval size.
+    -> Wire s e m a a
+sAvg int =
+    mkSF $ \ds x ->
+        let t = dtime ds in
+        (x, loop t (Tl.singleton t x))
+
+    where
+    loop t' tl' =
+        mkSF $ \ds x ->
+            let t  = t' + dtime ds
+                t0 = t - int
+                tl = Tl.scCutL t0 (Tl.insert t x tl')
+                a  = Tl.scAvg t0 t tl
+            in (a, loop t tl)
+
+
+-- | Produce a staircase graph for the given points in time, where the
+-- magnitudes of the points are distances from /now/.
+--
+-- See also 'lGraph'.
+--
+-- Example: @sGraph [0, 1, 2]@ will output the inputs at /now/, one
+-- second before now and two seconds before now.
+--
+-- * Complexity: O(s) space, O(n * log s) time, where s = number of
+--   samples in the interval, n = number of requested data points.
+--
+-- * Depends: now.
+
+sGraph ::
+    (Fractional t, HasTime t s)
+    => [t]  -- ^ Data points to produce.
+    -> Wire s e m a [a]
+sGraph qts =
+    mkSF $ \ds x ->
+        let t = dtime ds in
+        (x <$ qts, loop t (Tl.singleton t x))
+
+    where
+    earliest = maximum (map abs qts)
+
+    loop t' tl' =
+        mkSF $ \ds x ->
+            let t  = t' + dtime ds
+                tl = Tl.scCutL (t - earliest) (Tl.insert t x tl')
+                ps = map (\qt -> Tl.scLookup (t - abs qt) tl) qts
+            in (ps, loop t tl)
+
+
+-- | Graph the given interval from now with the given number of evenly
+-- distributed points in time.  Convenience interface to 'sGraph'.
+--
+-- See also 'lGraphN'.
+--
+-- * Complexity: O(s) space, O(n * log s) time, where s = number of
+--   samples in the interval, n = number of requested data points.
+--
+-- * Depends: now.
+
+sGraphN ::
+    (Fractional t, HasTime t s)
+    => t    -- ^ Interval to graph from now.
+    -> Int  -- ^ Number of data points to produce.
+    -> Wire s e m a [a]
+sGraphN int n
+    | int <= 0 = error "sGraphN: Non-positive interval"
+    | n <= 0   = error "sGraphN: Non-positive number of data points"
+sGraphN int n =
+    let n1   = n - 1
+        f qt = realToFrac int * fromIntegral qt / fromIntegral n1
+    in sGraph (map f [0..n1])
diff --git a/FRP/Netwire/Move.hs b/FRP/Netwire/Move.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Netwire/Move.hs
@@ -0,0 +1,77 @@
+-- |
+-- Module:     FRP.Netwire.Move
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module FRP.Netwire.Move
+    ( -- * Calculus
+      derivative,
+      integral,
+      integralWith
+    )
+    where
+
+import Control.Wire
+
+
+-- | Time derivative of the input signal.
+--
+-- * Depends: now.
+--
+-- * Inhibits: at singularities.
+
+derivative ::
+    (RealFloat a, HasTime t s, Monoid e)
+    => Wire s e m a a
+derivative = mkPure $ \_ x -> (Left mempty, loop x)
+    where
+    loop x' =
+        mkPure $ \ds x ->
+            let dt  = realToFrac (dtime ds)
+                dx  = (x - x') / dt
+                mdx | isNaN dx      = Right 0
+                    | isInfinite dx = Left mempty
+                    | otherwise     = Right dx
+            in mdx `seq` (mdx, loop x)
+
+
+-- | Integrate the input signal over time.
+--
+-- * Depends: before now.
+
+integral ::
+    (Fractional a, HasTime t s)
+    => a  -- ^ Integration constant (aka start value).
+    -> Wire s e m a a
+integral x' =
+    mkPure $ \ds dx ->
+        let dt = realToFrac (dtime ds)
+        in x' `seq` (Right x', integral (x' + dt*dx))
+
+
+-- | Integrate the left input signal over time, but apply the given
+-- correction function to it.  This can be used to implement collision
+-- detection/reaction.
+--
+-- The right signal of type @w@ is the /world value/.  It is just passed
+-- to the correction function for reference and is not used otherwise.
+--
+-- The correction function must be idempotent with respect to the world
+-- value: @f w (f w x) = f w x@.  This is necessary and sufficient to
+-- protect time continuity.
+--
+-- * Depends: before now.
+
+integralWith ::
+    (Fractional a, HasTime t s)
+    => (w -> a -> a)  -- ^ Correction function.
+    -> a              -- ^ Integration constant (aka start value).
+    -> Wire s e m (a, w) a
+integralWith correct = loop
+    where
+    loop x' =
+        mkPure $ \ds (dx, w) ->
+            let dt = realToFrac (dtime ds)
+                x  = correct w (x' + dt*dx)
+            in x' `seq` (Right x', loop x)
diff --git a/FRP/Netwire/Noise.hs b/FRP/Netwire/Noise.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Netwire/Noise.hs
@@ -0,0 +1,98 @@
+-- |
+-- Module:     FRP.Netwire.Noise
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module FRP.Netwire.Noise
+    ( -- * Noise generators
+      noise,
+      noiseR,
+      wackelkontakt,
+
+      -- * Convenience
+      stdNoise,
+      stdNoiseR,
+      stdWackelkontakt
+    )
+    where
+
+import Control.Wire
+import Prelude hiding ((.), id)
+import System.Random
+
+
+-- | Noise events with the given distance between events.  Use 'hold' or
+-- 'holdFor' to generate a staircase.
+
+noise ::
+    (HasTime t s, Random b, RandomGen g)
+    => t  -- ^ Time period.
+    -> g  -- ^ Random number generator.
+    -> Wire s e m a (Event b)
+noise int | int <= 0 = error "noise: Non-positive interval"
+noise int = periodicList int . randoms
+
+
+-- | Noise events with the given distance between events.  Noise will be
+-- in the given range.  Use 'hold' or 'holdFor' to generate a staircase.
+
+noiseR ::
+    (HasTime t s, Random b, RandomGen g)
+    => t       -- ^ Step duration.
+    -> (b, b)  -- ^ Noise range.
+    -> g       -- ^ Random number generator.
+    -> Wire s e m a (Event b)
+noiseR int _ | int <= 0 = error "noiseR: Non-positive interval"
+noiseR int r = periodicList int . randomRs r
+
+
+-- | Convenience interface to 'noise' for 'StdGen'.
+
+stdNoise ::
+    (HasTime t s, Random b)
+    => t    -- ^ Step duration.
+    -> Int  -- ^ 'StdGen' seed.
+    -> Wire s e m a (Event b)
+stdNoise int = noise int . mkStdGen
+
+
+-- | Convenience interface to 'noiseR' for 'StdGen'.
+
+stdNoiseR ::
+    (HasTime t s, Monad m, Random b)
+    => t       -- ^ Step duration.
+    -> (b, b)  -- ^ Noise range.
+    -> Int     -- ^ 'StdGen' seed.
+    -> Wire s e m a (Event b)
+stdNoiseR int r = noiseR int r . mkStdGen
+
+
+-- | Convenience interface to 'wackelkontakt' for 'StdGen'.
+
+stdWackelkontakt ::
+    (HasTime t s, Monad m, Monoid e)
+    => t    -- ^ Step duration.
+    -> Double    -- ^ Probability to produce.
+    -> Int  -- ^ 'StdGen' seed.
+    -> Wire s e m a a
+stdWackelkontakt int p = wackelkontakt int p . mkStdGen
+
+
+-- | Randomly produce or inhibit with the given probability, each time
+-- for the given duration.
+--
+-- The name /Wackelkontakt/ (German for /slack joint/) is a Netwire
+-- running gag.  It makes sure that you revisit the documentation from
+-- time to time. =)
+--
+-- * Depends: now.
+
+wackelkontakt ::
+    (HasTime t s, Monad m, Monoid e, RandomGen g)
+    => t  -- ^ Duration.
+    -> Double  -- ^ Probability to produce.
+    -> g  -- ^ Random number generator.
+    -> Wire s e m a a
+wackelkontakt int _ _ | int <= 0 = error "wackelkontakt: Non-positive duration"
+wackelkontakt int p g = fmap snd $ when (< p) . hold . noise int g &&& id
diff --git a/FRP/Netwire/Utils/Timeline.hs b/FRP/Netwire/Utils/Timeline.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Netwire/Utils/Timeline.hs
@@ -0,0 +1,176 @@
+-- |
+-- Module:     FRP.Netwire.Utils.Timeline
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module FRP.Netwire.Utils.Timeline
+    ( -- * Time lines for statistics wires
+      Timeline,
+
+      -- * Constructing time lines
+      insert,
+      singleton,
+      union,
+
+      -- * Linear sampling
+      linAvg,
+      linCutL,
+      linCutR,
+      linLookup,
+
+      -- * Staircase sampling
+      scAvg,
+      scCutL,
+      scCutR,
+      scLookup
+    )
+    where
+
+import qualified Data.Map.Strict as M
+import Control.Applicative
+import Data.Data
+import Data.Map.Strict (Map)
+
+
+-- | A time line is a non-empty set of samples together with time
+-- information.
+
+newtype Timeline t a =
+    Timeline {
+      timeline :: Map t a
+    }
+    deriving (Data, Eq, Ord, Read, Show, Typeable)
+
+instance Functor (Timeline t) where
+    fmap f (Timeline m) = Timeline (M.map f m)
+
+
+-- | Insert the given data point.
+
+insert :: (Ord t) => t -> a -> Timeline t a -> Timeline t a
+insert t x (Timeline m) = Timeline (M.insert t x m)
+
+
+-- | Linearly interpolate the points in the time line, integrate the
+-- given time interval of the graph, divide by the interval length.
+
+linAvg ::
+    (Fractional a, Fractional t, Real t)
+    => t -> t -> Timeline t a -> a
+linAvg t0 t1
+    | t0 > t1 = const (error "linAvg: Invalid interval")
+    | t0 == t1 = linLookup t0
+linAvg t0 t1 = avg 0 . M.assocs . timeline . linCutR t1 . linCutL t0
+    where
+    avg a' ((t', y1) : xs@((t, y2) : _)) =
+        let dt = realToFrac (t - t')
+            a  = a' + dt*(y1 + y2)/2
+        in a `seq` avg a xs
+    avg a' _ = a' / realToFrac (t1 - t0)
+
+
+-- | Cut the timeline at the given point in time @t@, such that all
+-- samples up to but not including @t@ are forgotten.  The most recent
+-- sample before @t@ is moved and interpolated accordingly.
+
+linCutL ::
+    (Fractional a, Fractional t, Real t)
+    => t -> Timeline t a -> Timeline t a
+linCutL t tl@(Timeline m) =
+    Timeline $
+    case M.splitLookup t m of
+      (_, Just x, mr) -> M.insert t x mr
+      (_, _, mr)      -> M.insert t (linLookup t tl) mr
+
+
+-- | Cut the timeline at the given point in time @t@, such that all
+-- samples later than @t@ are forgotten.  The most recent sample after
+-- @t@ is moved and interpolated accordingly.
+
+linCutR ::
+    (Fractional a, Fractional t, Real t)
+    => t -> Timeline t a -> Timeline t a
+linCutR t tl@(Timeline m) =
+    Timeline $
+    case M.splitLookup t m of
+      (ml, Just x, _) -> M.insert t x ml
+      (ml, _, _)      -> M.insert t (linLookup t tl) ml
+
+
+-- | Look up with linear sampling.
+
+linLookup :: (Fractional a, Fractional t, Real t) => t -> Timeline t a -> a
+linLookup t (Timeline m) =
+    case M.splitLookup t m of
+      (_, Just x, _) -> x
+      (ml, _, mr)    ->
+          case (fst <$> M.maxViewWithKey ml, fst <$> M.minViewWithKey mr) of
+            (Just (t1, x1), Just (t2, x2)) ->
+                let f = realToFrac ((t - t1) / (t2 - t1))
+                in x1*(1 - f) + x2*f
+            (Just (_, x), _) -> x
+            (_, Just (_, x)) -> x
+            _                -> error "linLookup: BUG: querying empty Timeline"
+
+
+-- | Integrate the given time interval of the staircase, divide by the
+-- interval length.
+
+scAvg :: (Fractional a, Real t) => t -> t -> Timeline t a -> a
+scAvg t0 t1
+    | t0 > t1 = const (error "scAvg: Invalid interval")
+    | t0 == t1 = scLookup t0
+scAvg t0 t1 = avg 0 . M.assocs . timeline . scCutR t1 . scCutL t0
+    where
+    avg a' ((t', y) : xs@((t, _) : _)) =
+        let dt = realToFrac (t - t')
+            a  = a' + dt*y
+        in a `seq` avg a xs
+    avg a' _ = a' / realToFrac (t1 - t0)
+
+
+-- | Cut the timeline at the given point in time @t@, such that all
+-- samples up to but not including @t@ are forgotten.  The most recent
+-- sample before @t@ is moved accordingly.
+
+scCutL :: (Ord t) => t -> Timeline t a -> Timeline t a
+scCutL t tl@(Timeline m) =
+    Timeline $
+    case M.splitLookup t m of
+      (_, Just x, mr) -> M.insert t x mr
+      (_, _, mr)      -> M.insert t (scLookup t tl) mr
+
+
+-- | Cut the timeline at the given point in time @t@, such that all
+-- samples later than @t@ are forgotten.  The earliest sample after @t@
+-- is moved accordingly.
+
+scCutR :: (Ord t) => t -> Timeline t a -> Timeline t a
+scCutR t tl@(Timeline m) =
+    Timeline $
+    case M.splitLookup t m of
+      (ml, Just x, _) -> M.insert t x ml
+      (ml, _, _)      -> M.insert t (scLookup t tl) ml
+
+
+-- | Look up on staircase.
+
+scLookup :: (Ord t) => t -> Timeline t a -> a
+scLookup t (Timeline m) =
+    case (M.lookupLE t m, M.lookupGE t m) of
+      (Just (_, x), _) -> x
+      (_, Just (_, x)) -> x
+      _                -> error "linLookup: BUG: querying empty Timeline"
+
+
+-- | Singleton timeline with the given point.
+
+singleton :: t -> a -> Timeline t a
+singleton t = Timeline . M.singleton t
+
+
+-- | Union of two time lines.  Right-biased.
+
+union :: (Ord t) => Timeline t a -> Timeline t a -> Timeline t a
+union (Timeline m1) (Timeline m2) = Timeline (M.union m2 m1)
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,5 @@
-Netwire license
-Copyright (c) 2012, Ertugrul Soeylemez
+netwire license
+Copyright (c) 2013, Ertugrul Soeylemez
 
 All rights reserved.
 
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,437 @@
+Netwire
+=======
+
+Netwire is a functional reactive programming (FRP) library with signal
+inhibition.  It implements three related concepts, *wires*, *intervals*
+and *events*, the most important of which is the *wire*.  To work with
+wires we will need a few imports:
+
+    import FRP.Netwire
+    import Prelude hiding ((.), id)
+
+The `FRP.Netwire` module exports the basic types and helper functions.
+It also has some convenience reexports you will pretty much always need
+when working with wires, including `Control.Category`.  This is why we
+need the explicit `Prelude` import.
+
+In general wires are generalized automaton arrows, so you can express
+many design patterns using them.  The `FRP.Netwire` module provides a
+proper FRP framework based on them, which strictly respects continuous
+time and discrete event semantics.  When developing a framework based on
+Netwire, e.g. a GUI library or a game engine, you may want to import
+`Control.Wire` instead.
+
+
+Introduction
+------------
+
+The following type is central to the entire library:
+
+    data Wire s e m a b
+
+Don't worry about the large number of type arguments.  They all have
+very simple meanings, which will be explained below.
+
+A value of this type is called a *wire* and represents a *reactive*
+value of type $b$, that is a value that may change over time.  It may
+depend on a reactive value of type $a$.  In a sense a wire is a function
+from a reactive value of type $a$ to a reactive value of type $b$, so
+whenever you see something of type `Wire s e m a b` your mind should
+draw an arrow from $a$ to $b$.  In FRP terminology a reactive value is
+called a *behavior*.
+
+A constant reactive value can be constructed using `pure`:
+
+    pure 15
+
+This wire is the reactive value 15.  It does not depend on other
+reactive values and does not change over time.  This suggests that there
+is an applicative interface to wires, which is indeed the case:
+
+    liftA2 (+) (pure 15) (pure 17)
+
+This reactive value is the sum of two reactive values, each of which is
+just a constant, 15 and 17 respectively.  So this is the constant
+reactive value 32.  Let's spell out its type:
+
+    myWire :: (Monad m, Num b) => Wire s e m a b
+    myWire = liftA2 (+) (pure 15) (pure 17)
+
+This indicates that $m$ is some kind of underlying monad.  As an
+application developer you don't have to concern yourself much about it.
+Framework developers can use it to allow wires to access environment
+values through a reader monad or to produce something (like a GUI)
+through a writer monad.
+
+The wires we have seen so far are rather boring.  Let's look at a more
+interesting one:
+
+    time :: (HasTime t s) => Wire s e m a t
+
+This wire represents the current local time, which starts at zero when
+execution begins.  It does not make any assumptions about the time type
+other than that it is a numeric type with a `Real` instance.  This is
+enforced implicitly by the `HasTime` constraint.
+
+The type of this wire gives some insight into the $s$ parameter.  Wires
+are generally pure and do not have access to the system clock or other
+run-time information.  The timing information has to come from outside
+and is passed to the wire through a value of type $s$, called the *state
+delta*.  We will learn more about this in the next section about
+executing wires.
+
+Since there is an applicative interface you can also apply `fmap` to a
+wire to apply a function to its value:
+
+    fmap (2*) time
+
+This reactive value is a clock that is twice as fast as the regular
+local time clock.  If you use system time as your clock, then the time
+type $t$ will most likely be `NominalDiffTime` from `Data.Time.Clock`.
+However, you will usually want to have time of type `Double` or some
+other floating point type.  There is a predefined wire for this:
+
+    timeF :: (Fractional b, HasTime t s, Monad m) => Wire s e m a b
+    timeF = fmap realToFrac time
+
+If you think of reactive values as graphs with the horizontal axis
+representing time, then the `time` wire is just a straight diagonal line
+and constant wires (constructed by `pure`) are just horizontal lines.
+You can use the applicative interface to perform arithmetic on them:
+
+    liftA2 (\t c -> c - 2*t) time (pure 60)
+
+This gives you a countdown clock that starts at 60 and runs twice as
+fast as the regular clock.  So it after two seconds its value will be
+56, decreasing by 2 each second.
+
+
+Testing wires
+-------------
+
+Enough theory, we wanna see some performance now!  Let's write a simple
+program to test a constant (`pure`) wire:
+
+    import Control.Wire
+    import Prelude hiding ((.), id)
+
+    wire :: (Monad m) => Wire s () m a Integer
+    wire = pure 15
+
+    main :: IO ()
+    main = testWire (pure ()) wire
+
+This should just display the value 15.  Abort the program by pressing
+Ctrl-C.  The `testWire` function is a convenience to examine wires.  It
+just executes the wire and continuously prints its value to stdout:
+
+    testWire ::
+        (MonadIO m, Show b, Show e)
+        => Session m s
+        -> (forall a. Wire s e Identity a b)
+        -> m c
+
+The type signatures in Netwire are known to be scary. =) But like most
+of the library the underlying meaning is actually very simple.
+Conceptually the wire is run continuously step by step, at each step
+increasing its local time slightly.  This process is traditionally
+called *stepping*.
+
+As an FRP developer you assume a continuous time model, so you don't
+observe this stepping process from the point of view of your reactive
+application, but it can be useful to know that wire execution is
+actually a discrete process.
+
+The first argument of `testWire` needs some explanation.  It is a recipe
+for state deltas.  In the above example we have just used `pure ()`,
+meaning that we don't use anything stateful from the outside world,
+particularly we don't use a clock.  From the type signature it is also
+clear that this sets `s = ()`.
+
+The second argument is the wire to run.  The input type is quantified
+meaning that it needs to be polymorphic in its input type.  In other
+words it means that the wire does not depend on any other reactive
+value.  The underlying monad is `Identity` with the obvious meaning that
+this wire cannot have any monadic effects.
+
+The following application just displays the number of seconds passed
+since program start (with some subsecond precision):
+
+    wire :: (HasTime t s) => Wire s () m a t
+    wire = time
+
+    main :: IO ()
+    main = testWire clockSession_ wire
+
+Since this time the wire actually needs a clock we use `clockSession_`
+as the second argument:
+
+    clockSession_ ::
+        (Applicative m, MonadIO m)
+        => Session m (Timed NominalDiffTime ())
+
+It will instantiate $s$ to be `Timed NominalDiffTime ()`.  This type
+indeed has a `HasTime` instance with $t$ being `NominalDiffTime`.  In
+simpler words it provides a clock to the wire.  At first it may seem
+weird to use `NominalDiffTime` instead of something like `UTCTime`, but
+this is reasonable, because time is relative to the wire's start time.
+Also later in the section about switching we will see that a wire does
+not necessarily start when the program starts.
+
+
+Constructing wires
+------------------
+
+Now that we know how to test wires we can start constructing more
+complicated wires.  First of all it is handy that there are many
+convenience instances, including `Num`.  Instead of `pure 15` we can
+simply write `15`.  Also instead of
+
+    liftA2 (+) time (pure 17)
+
+we can simply write:
+
+    time + 17
+
+This clock starts at 17 instead of zero.  Let's make it run twice as
+fast:
+
+    2*time + 17
+
+If you have trouble wrapping your head around such an expression it may
+help to read `a*b + c` mathematically as $a(t) b(t) + c(t)$ and read
+`time` as simply $t$.
+
+So far we have seen wires that ignore their input.  The following wire
+uses its input:
+
+    integral 5
+
+It literally integrates its input value with respect to time.  Its
+argument is the integration constant, i.e. the start value.  To supply
+an input simply compose it:
+
+    integral 5 . 3
+
+Remember that `3` really means `pure 3`, a constant wire.  The integral
+of the constant 3 is $3 t + c$ and here $c = 5$.  Here is another
+example:
+
+    integral 5 . time
+
+Since `time` denotes $t$ the integral will be $\frac{1}{2} t^2 + c$,
+again with $c = 5$.  This may sound like a complicated, sophisticated
+wire, but it's really not.  Surprisingly there is no crazy algebra or
+complicated numerical algorithm going on under the hood.  Integrating
+over time requires one addition and one division each frame.  So there
+is nothing wrong with using it extensively to animate a scene or to move
+objects in a game.
+
+Sometimes categorical composition and the applicative interface can be
+inconvenient, in which case you may choose to use the arrow interface.
+The above integration can be expressed the following way:
+
+    proc _ -> do
+        t <- time -< ()
+        integral 5 -< t
+
+Since `time` ignores its input signal, we just give it a constant signal
+with value `()`.  We name time's value $t$ and pass it as the input
+signal to `integral`.
+
+
+Intervals
+---------
+
+Wires may choose to produce a signal only for a limited amount of time.
+We refer to those wires as intervals.  When a wire does not produce,
+then it *inhibits*.  Example:
+
+    for 3
+
+This wire acts like the identity wire in that it passes its input signal
+through unchanged:
+
+    for 3 . "yes"
+
+The signal of this wire will be "yes", but after three seconds it will
+stop to act like the identity wire and will inhibit forever.
+
+When you use `testWire` inhibition will be displayed as "I:" followed by
+a value, the *inhibition value*.  This is what the $e$ parameter to
+`Wire` is.  It's called the *inhibition monoid*:
+
+    for :: (HasTime t s, Monoid e) => t -> Wire s e m a a
+
+As you can see the input and output types are the same and fully
+polymorphic, hinting at the identity-like behavior.  All predefined
+intervals inhibit with the `mempty` value.  When the wire inhibits, you
+don't get a signal of type $a$, but rather an inhibition value of type
+$e$.  Netwire does not interpret this value in any way and in most cases
+you would simply use `e = ()`.
+
+Intervals give you a very elegant way to combine wires:
+
+    for 3 . "yes" <|> "no"
+
+This wire produces "yes" for three seconds.  Then the wire to the left
+of `<|>` will stop producing, so `<|>` will use the wire to its right
+instead.  You can read the operator as a left-biased "or".  The signal
+of the wire `w1 <|> w2` will be the signal of the leftmost component
+wire that actually produced a signal.  There are a number of predefined
+interval wires.  The above signal can be written equivalently as:
+
+    after 3 . "no" <|> "yes"
+
+The left wire will inhibit for the first three seconds, so during that
+interval the right wire is chosen.  After that, as suggested by its
+name, the `after` wire starts acting like the identity wire, so the left
+side takes precedence.  Once the time period has passed the `after` wire
+will produce forever, leaving the "yes" wire never to be reached again.
+However, you can easily combine intervals:
+
+    after 5 . for 6 . "Blip!" <|> "Look at me..."
+
+The left wire will produce after five seconds from the beginning for six
+seconds from the beginning, so effectively it will produce for one
+second.  When you animate this wire, you will see the string "Look at
+me..." for five seconds, then you will see "Blip!" for one second, then
+finally it will go back to "Look at me..." and display that one forever.
+
+
+Events
+------
+
+Events are things that happen at certain points in time.  Examples
+include button presses, network packets or even just reaching a certain
+point in time.  As such they can be thought of as lists of values
+together with their occurrence times.  Events are actually first class
+signals of the `Event` type:
+
+    data Event a
+
+For example the predefined `never` event is the event that never occurs:
+
+    never :: Wire s e m a (Event b)
+
+As suggested by the type events contain a value.  Netwire does not
+export the constructors of the `Event` type by default.  If you are a
+framework developer you can import the `Control.Wire.Unsafe.Event`
+module to implement your own events.  A game engine may include events
+for key presses or certain things happening in the scene.  However, as
+an application developer you should view this type as being opaque.
+This is necessary in order to protect continuous time semantics.  You
+cannot access event values directly.
+
+There are a number of ways to respond to an event.  The primary way to
+do this in Netwire is to turn events into intervals.  There are a number
+of predefined wires for that purpose, for example `asSoonAs`:
+
+    asSoonAs :: (Monoid e) => Wire s e m (Event a) a
+
+This wire takes an event signal as its input.  Initially it inhibits,
+but as soon as the event occurs for the first time, it produces the
+event's last value forever.  The `at` event will occur only once after
+the given time period has passed:
+
+    at :: (HasTime t s) => t -> Wire s e m a (Event a)
+
+Example:
+
+    at 3 . "blubb"
+
+This event will occur after three seconds, and the event's value will be
+"blubb".  Using `asSoonAs` we can turn this into an interval:
+
+    asSoonAs . at 3 . "blubb"
+
+This wire will inhibit for three seconds and then start producing.  It
+will produce the value "blubb" forever.  That's the event's last value
+after three seconds, and it will never change, because the event does
+not occur ever again.  Here is an example that may be more
+representative of that property:
+
+    asSoonAs . at 3 . time
+
+This wire inhibits for three seconds, then it produces the value 3 (or a
+value close to it) forever.  Notice that this is not a clock.  It does
+not produce the current time, but the `time` at the point in time when
+the event occurred.
+
+To combine multiple events there are a number of options.  In principle
+you should think of event values to form a semigroup (of your choice),
+because events can occur simultaneously.  However, in many cases the
+actual value of the event is not that interesting, so there is an easy
+way to get a left- or right-biased combination:
+
+    (at 2 <& at 3) . time
+
+This event occurs two times, namely once after two seconds and once
+after three seconds.  In each case the event value will be the
+occurrence time.  Here is an interesting case:
+
+    at 2 . "blah" <& at 2 . "blubb"
+
+These events will occur simultaneously.  The value will be "blah",
+because `<&` means left-biased combination.  There is also `&>` for
+right-biased combination.  If event values actually form a semigroup,
+then you can just use monoidal composition:
+
+    at 2 . "blah" <> at 2 . "blubb"
+
+Again these events occur at the same time, but this time the event value
+will be "blahblubb".  Note that you are using two Monoid instances and
+one Semigroup instance here.  If the signals of two wires form a monoid,
+then wires themselves form a monoid:
+
+    w1 <> w2 = liftA2 (<>) w1 w2
+
+There are many predefined event-wires and many combinators for
+manipulating events in the `Control.Wire.Event` module.  A common events
+is the `now` event:
+
+    now :: Wire s e m a (Event a)
+
+This event occurs once at the beginning.
+
+
+Switching
+---------
+
+We still lack a meaningful way to respond to events.  This is where
+*switching* comes in, sometimes also called *dynamic switching*.  The
+most important combinator for switching is `-->`:
+
+    w1 --> w2
+
+The idea is really straightforward:  This wire acts like `w1` as long as
+it produces.  As soon as it stops producing it is discarded and `w2`
+takes its place.  Example:
+
+    for 3 . "yes" --> "no"
+
+In this case the behavior will be the same as in the *intervals*
+section, but with two major differences:  Firstly when the first
+interval ends, it is completely discarded and garbage-collected, never
+to be seen again.  Secondly and more importantly the point in time of
+switching will be the beginning for the new wire.  Example:
+
+    for 3 . time --> time
+
+This wire will show a clock counting to three seconds, then it will
+start over from zero.  This is why we usually refer to time as *local
+time*.
+
+Recursion is fully supported.  Here is a fun example:
+
+    netwireIsCool =
+        for 2 . "Once upon a time..." -->
+        for 3 . "... games were completely imperative..." -->
+        for 2 . "... but then..." -->
+        for 10 . ("Netwire 5! " <> anim) -->
+        netwireIsCool
+
+      where
+        anim =
+            holdFor 0.5 . periodic 1 . "Hoo..." <|>
+            "...ray!"
diff --git a/Setup.lhs b/Setup.lhs
--- a/Setup.lhs
+++ b/Setup.lhs
@@ -1,5 +1,5 @@
-Netwire setup script
-Copyright (C) 2012, Ertugrul Soeylemez
+netwire setup script
+Copyright (C) 2013, Ertugrul Soeylemez
 
 Please see the LICENSE file for terms and conditions of use,
 modification and distribution of this package, including this file.
diff --git a/default.nix b/default.nix
new file mode 100644
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,30 @@
+# -*-conf-*-
+
+{ }:
+with import <nixpkgs> { };
+
+let
+  hs = haskellPackages;
+  inherit (hs) cabal;
+in rec {
+
+  netwire =
+    cabal.mkDerivation (self : rec {
+      pname = "netwire";
+      version = "5.0.0";
+      isLibrary = true;
+      isExecutable = false;
+
+      src = ./dist/netwire- + "${version}.tar.gz";
+
+      buildDepends = [
+        hs.parallel
+        hs.QuickCheck
+        hs.semigroups
+        hs.testFramework
+        hs.testFrameworkQuickcheck2
+        hs.testFrameworkTh
+      ];
+    });
+
+}
diff --git a/netwire.cabal b/netwire.cabal
--- a/netwire.cabal
+++ b/netwire.cabal
@@ -1,90 +1,99 @@
-Name:          netwire
-Version:       4.0.7
-Category:      Control, FRP
-Synopsis:      Flexible wire arrows for FRP
-Maintainer:    Ertugrul Söylemez <es@ertes.de>
-Author:        Ertugrul Söylemez <es@ertes.de>
-Copyright:     (c) 2012 Ertugrul Söylemez
-License:       BSD3
-License-file:  LICENSE
-Build-type:    Simple
-Stability:     experimental
-Cabal-version: >= 1.10
-Description:
-    Efficient and flexible wire arrows for functional reactive programming
-    and other forms of locally stateful programming.
+name:          netwire
+version:       5.0.0
+category:      FRP
+synopsis:      Functional reactive programming library
+maintainer:    Ertugrul Söylemez <es@ertes.de>
+author:        Ertugrul Söylemez <es@ertes.de>
+copyright:     (c) 2013 Ertugrul Söylemez
+license:       BSD3
+license-file:  LICENSE
+build-type:    Simple
+cabal-version: >= 1.10
+extra-source-files: README.md default.nix
+description:
+    This library provides interfaces for and implements wire arrows
+    useful both for functional reactive programming (FRP) and locally
+    stateful programming (LSP).
 
+flag TestProgram
+    default: False
+    description: Build the test program
+    manual: True
+
 Source-repository head
     type:     darcs
-    location: http://darcs.ertes.de/netwire/
+    location: http://hub.darcs.net/ertes/netwire
 
-Library
-    Build-depends:
-        base          >= 4.0 && < 5,
-        bifunctors    >= 0.1 && < 4,
-        containers    >= 0.4 && < 1,
-        deepseq       >= 1.3 && < 2,
-        lifted-base   >= 0.1 && < 1,
-        monad-control >= 0.3 && < 1,
-        mtl           >= 2.0 && < 3,
-        profunctors   >= 0.1 && < 4,
-        random        >= 1.0 && < 2,
-        semigroups    >= 0.8 && < 1,
-        tagged        >= 0.4 && < 1,
-        time          >= 1.4 && < 2,
-        vector-space  >= 0.8 && < 1
-    Default-language: Haskell2010
-    Default-extensions:
-        BangPatterns
+library
+    build-depends:
+        base         >= 4.5 && < 5,
+        containers   >= 0.5 && < 1,
+        deepseq      >= 1.3 && < 2,
+        parallel     >= 3.2 && < 4,
+        random       >= 1.0 && < 2,
+        semigroups   >= 0.9 && < 1,
+        transformers >= 0.3 && < 1,
+        time         >= 1.4 && < 2
+    default-language: Haskell2010
+    default-extensions:
         DeriveDataTypeable
-        FlexibleContexts
+        DeriveFoldable
+        DeriveFunctor
+        DeriveTraversable
         FlexibleInstances
+        FunctionalDependencies
+        GADTs
         MultiParamTypeClasses
         RankNTypes
-        ScopedTypeVariables
         TupleSections
-        TypeFamilies
-    GHC-Options: -W
-    Exposed-modules:
+    ghc-options: -W
+    exposed-modules:
         Control.Wire
-        Control.Wire.Classes
-        Control.Wire.Prefab
-        Control.Wire.Prefab.Accum
-        Control.Wire.Prefab.Analyze
-        Control.Wire.Prefab.Effect
-        Control.Wire.Prefab.Event
-        Control.Wire.Prefab.List
-        Control.Wire.Prefab.Move
-        Control.Wire.Prefab.Noise
-        Control.Wire.Prefab.Queue
-        Control.Wire.Prefab.Sample
-        Control.Wire.Prefab.Simple
-        Control.Wire.Prefab.Time
+        Control.Wire.Core
+        Control.Wire.Event
+        Control.Wire.Interval
+        Control.Wire.Run
         Control.Wire.Session
-        Control.Wire.TimedMap
-        Control.Wire.Trans
-        Control.Wire.Trans.Combine
-        Control.Wire.Trans.Embed
-        Control.Wire.Trans.Event
-        Control.Wire.Trans.Simple
-        Control.Wire.Trans.Switch
-        Control.Wire.Trans.Time
-        Control.Wire.Types
-        Control.Wire.Wire
+        Control.Wire.Switch
+        Control.Wire.Time
+        Control.Wire.Unsafe.Event
+        FRP.Netwire
+        FRP.Netwire.Analyze
+        FRP.Netwire.Move
+        FRP.Netwire.Noise
+        FRP.Netwire.Utils.Timeline
 
--- Executable netwire-test
---     Build-depends:
---         base >= 4 && < 5,
---         containers,
+executable netwire-test
+    build-depends:
+        base >= 4.5 && < 5,
+        containers,
+        netwire
+    default-language: Haskell2010
+    default-extensions:
+        Arrows
+        OverloadedStrings
+        RecursiveDo
+    ghc-options: -threaded -rtsopts
+    hs-source-dirs: test
+    main-is: Test.hs
+    if flag(testprogram)
+        buildable: True
+    else
+        buildable: False
+
+-- test-suite tests
+--     type: exitcode-stdio-1.0
+--     build-depends:
+--         base >= 4.5 && < 5,
 --         netwire,
---         random,
---         time
---     Default-language: Haskell2010
---     Default-extensions:
---         Arrows
---         OverloadedStrings
---         RecursiveDo
---         TupleSections
---     Hs-source-dirs: test
---     Main-is: Main.hs
---     GHC-Options: -threaded -rtsopts
+--         QuickCheck,
+--         test-framework,
+--         test-framework-quickcheck2,
+--         test-framework-th,
+--         vty
+--     default-language: Haskell2010
+--     default-extensions:
+--         TemplateHaskell
+--     ghc-options: -W -threaded -rtsopts -with-rtsopts=-N
+--     hs-source-dirs: test
+--     main-is: Props.hs
diff --git a/test/Test.hs b/test/Test.hs
new file mode 100644
--- /dev/null
+++ b/test/Test.hs
@@ -0,0 +1,20 @@
+-- |
+-- Module:     Main
+-- Copyright:  (c) 2013 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+
+module Main where
+
+import Control.Monad.Fix
+import Control.Wire
+import Prelude hiding ((.), id)
+
+
+wire :: SimpleWire a String
+wire =
+    holdFor 0.5 . periodicList 1 (cycle ["a", "b", "c"]) <|> "---"
+
+
+main :: IO ()
+main = testWire clockSession_ wire
