diff --git a/FRP/NetWire.hs b/FRP/NetWire.hs
--- a/FRP/NetWire.hs
+++ b/FRP/NetWire.hs
@@ -10,7 +10,7 @@
 
 module FRP.NetWire
     ( -- * Wires
-      Wire, Event, Output, Time,
+      Wire, Output, Time,
 
       -- * Reactive sessions
       Session,
@@ -24,6 +24,11 @@
       stepSF,
       stepWirePure,
 
+      -- * Inhibition
+      InhibitException(..),
+      inhibitEx,
+      noEvent,
+
       -- * Netwire Reexports
       module FRP.NetWire.Analyze,
       module FRP.NetWire.Calculus,
@@ -36,10 +41,14 @@
       module FRP.NetWire.Tools,
 
       -- * Other convenience reexports
+      module Control.Monad.IO.Class,
+      module Control.Monad.IO.Control,
       module Data.Functor.Identity
     )
     where
 
+import Control.Monad.IO.Class
+import Control.Monad.IO.Control
 import Data.Functor.Identity
 import FRP.NetWire.Analyze
 import FRP.NetWire.Calculus
diff --git a/FRP/NetWire/Analyze.hs b/FRP/NetWire/Analyze.hs
--- a/FRP/NetWire/Analyze.hs
+++ b/FRP/NetWire/Analyze.hs
@@ -36,6 +36,8 @@
 --
 -- If you need an average over all samples ever produced, consider using
 -- 'avgAll' instead.
+--
+-- Never inhibits.  Feedback by delay.
 
 avg :: forall m v. (Fractional v, Monad m, NFData v, U.Unbox v) => Int -> Wire m v v
 avg n = mkGen $ \_ x -> return (Right x, avg' (U.replicate n (x/d)) x 0)
@@ -46,12 +48,12 @@
             let cur = let cur = succ cur' in if cur >= n then 0 else cur
                 x' = samples' U.! cur
                 samples =
-                    x' `seq` runST $ do
+                    x' `deepseq` runST $ do
                         s <- U.unsafeThaw samples'
                         UM.write s cur x
                         U.unsafeFreeze s
             let s = s' - x' + x
-            s `deepseq` return (Right s, avg' samples s cur)
+            s' `deepseq` cur `seq` return (Right s, avg' samples s cur)
 
     d :: v
     d = realToFrac n
@@ -62,6 +64,8 @@
 -- Please note that somewhat surprisingly this wire runs in constant
 -- space and is generally faster than 'avg', but most applications will
 -- benefit from averages over only the last few samples.
+--
+-- Never inhibits.  Feedback by delay.
 
 avgAll :: forall m v. (Fractional v, Monad m, NFData v) => Wire m v v
 avgAll = mkGen $ \_ x -> return (Right x, avgAll' 1 x)
@@ -71,7 +75,7 @@
         mkGen $ \_ x ->
             let n = n' + 1
                 a = a' - a'/n + x/n in
-            n `deepseq` a `deepseq` return (Right a, avgAll' n a)
+            n `deepseq` a' `deepseq` return (Right a, avgAll' n a)
 
 
 -- | Calculate the average number of frames per virtual second for the
@@ -81,6 +85,8 @@
 -- using the stepping functions in "FRP.NetWire.Session".  If this clock
 -- doesn't represent real time, then the output of this wire won't
 -- either.
+--
+-- Never inhibits.
 
 avgFps :: forall a m. Monad m => Int -> Wire m a Double
 avgFps = avgFps' . avg
@@ -95,35 +101,43 @@
 -- | Emits an event, whenever the input signal changes.  The event
 -- contains the last input value and the time elapsed since the last
 -- change.
+--
+-- Inhibits on no change.
 
-diff :: forall a m. (Eq a, Monad m) => Wire m a (Event (a, Time))
+diff :: forall a m. (Eq a, Monad m) => Wire m a (a, Time)
 diff =
     mkGen $ \(wsDTime -> dt) x' ->
-        return (Right Nothing, diff' dt x')
+        return (Left noEvent, diff' dt x')
 
     where
-    diff' :: Time -> a -> Wire m a (Event (a, Time))
+    diff' :: Time -> a -> Wire m a (a, Time)
     diff' t' x' =
         mkGen $ \(wsDTime -> dt) x ->
             let t = t' + dt in
             if x' == x
-              then return (Right Nothing, diff' t x')
-              else return (Right (Just (x', t)), diff' 0 x)
+              then return (Left noEvent, diff' t x')
+              else return (Right (x', t), diff' 0 x)
 
 
 -- | Return the high peak.
+--
+-- Never inhibits.  Feedback by delay.
 
 highPeak :: (Monad m, NFData a, Ord a) => Wire m a a
 highPeak = peakBy compare
 
 
 -- | Return the low peak.
+--
+-- Never inhibits.  Feedback by delay.
 
 lowPeak :: (Monad m, NFData a, Ord a) => Wire m a a
 lowPeak = peakBy (flip compare)
 
 
 -- | Return the high peak with the given comparison function.
+--
+-- Never inhibits.  Feedback by delay.
 
 peakBy :: forall a m. (Monad m, NFData a) => (a -> a -> Ordering) -> Wire m a a
 peakBy comp = mkGen $ \_ x -> return (Right x, peakBy' x)
@@ -132,4 +146,4 @@
     peakBy' p' =
         mkGen $ \_ x -> do
             let p = if comp x p' == GT then x else p'
-            p `deepseq` return (Right p, peakBy' p)
+            p' `deepseq` return (Right p, peakBy' p)
diff --git a/FRP/NetWire/Calculus.hs b/FRP/NetWire/Calculus.hs
--- a/FRP/NetWire/Calculus.hs
+++ b/FRP/NetWire/Calculus.hs
@@ -19,7 +19,9 @@
 import FRP.NetWire.Wire
 
 
--- | Differentiate over time.  Inhibits at first instant.
+-- | Differentiate over time.
+--
+-- Inhibits at first instant.
 
 derivative :: (Monad m, NFData v, VectorSpace v, Scalar v ~ Double) => Wire m v v
 derivative =
@@ -30,19 +32,28 @@
 
 -- | Differentiate over time.  The argument is the value before the
 -- first instant.
+--
+-- Never inhibits.  Direct feedback.
 
-derivativeFrom :: (Monad m, NFData v, VectorSpace v, Scalar v ~ Double) => v -> Wire m v v
-derivativeFrom y1 =
-    mkGen $ \(wsDTime -> dt) y2 -> do
-        let dy = (y2 ^-^ y1) ^/ dt
-        dy `deepseq` return (Right dy, derivativeFrom y2)
+derivativeFrom ::
+    forall m v. (Monad m, NFData v, VectorSpace v, Scalar v ~ Double) =>
+    v -> Wire m v v
+derivativeFrom y1 = derivativeFrom' zeroV y1
+    where
+    derivativeFrom' :: v -> v -> Wire m v v
+    derivativeFrom' dy' y1 =
+        mkGen $ \(wsDTime -> dt) y2 -> do
+            let dy = (y2 ^-^ y1) ^/ dt
+            dy' `deepseq` return (Right dy', derivativeFrom' dy y2)
 
 
 -- | Integrate over time.  The argument is the integration constant.
+--
+-- Never inhibits.  Direct feedback.
 
 integral :: (Monad m, NFData v, VectorSpace v, Scalar v ~ Double) => v -> Wire m v v
 integral x1 =
     mkGen $ \ws dx -> do
         let dt = wsDTime ws
             x2 = x1 ^+^ dt *^ dx
-        x2 `deepseq` return (Right x2, integral x2)
+        x1 `deepseq` return (Right x1, integral x2)
diff --git a/FRP/NetWire/Concurrent.hs b/FRP/NetWire/Concurrent.hs
--- a/FRP/NetWire/Concurrent.hs
+++ b/FRP/NetWire/Concurrent.hs
@@ -25,7 +25,7 @@
 import FRP.NetWire.Wire
 
 
--- | Concurrent version of '(***)'.  Passes its input signals to both
+-- | Concurrent version of '***'.  Passes its input signals to both
 -- argument wires concurrently.
 
 (~*~) :: Wire IO a c -> Wire IO b d -> Wire IO (a, b) (c, d)
@@ -41,7 +41,7 @@
 infixr 3 ~*~
 
 
--- | Concurrent version of '(&&&)'.  Passes its input signal to both
+-- | Concurrent version of '&&&'.  Passes its input signal to both
 -- argument wires concurrently.
 
 (~&~) :: Wire IO a b -> Wire IO a c -> Wire IO a (b, c)
@@ -50,7 +50,7 @@
 infixr 3 ~&~
 
 
--- | Concurrent version of '(<+>)'.  Passes its input signal to both
+-- | Concurrent version of '<+>'.  Passes its input signal to both
 -- argument wires concurrently, returning the result of the first wire
 -- which does not inhibit.
 
diff --git a/FRP/NetWire/Event.hs b/FRP/NetWire/Event.hs
--- a/FRP/NetWire/Event.hs
+++ b/FRP/NetWire/Event.hs
@@ -4,7 +4,8 @@
 -- License:    BSD3
 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>
 --
--- Events.
+-- Events.  None of these wires supports feedback, because they all can
+-- inhibit.
 
 module FRP.NetWire.Event
     ( -- * Producing events
@@ -14,14 +15,10 @@
       edgeBy,
       edgeJust,
       never,
-      now,
       once,
       repeatedly,
       repeatedlyList,
 
-      -- * Wire transformers
-      wait,
-
       -- * Event transformers
       -- ** Delaying events
       dam,
@@ -33,10 +30,8 @@
       notYet,
       takeEvents,
       takeFor,
-      -- ** Manipulating events
-      accum,
-      -- ** Mapping to continuous signals
-      hold, dHold
+      -- ** Tools
+      event
     )
     where
 
@@ -49,32 +44,16 @@
 import FRP.NetWire.Wire
 
 
--- | This function corresponds to the 'iterate' function for lists.
--- Begins with an initial output value, which is not emitted.  Each time
--- an input event is received, its function is applied to the current
--- accumulator and the new value is emitted.
-
-accum :: forall a m. Monad m => a -> Wire m (Event (a -> a)) (Event a)
-accum ee' = accum'
-    where
-    accum' :: Wire m (Event (a -> a)) (Event a)
-    accum' =
-        mkGen $ \_ ->
-            return .
-            maybe (Right Nothing, accum')
-                  (\f -> let ee = f ee' in ee `seq` (Right (Just ee), accum ee))
-
-
--- | Produce an event once after the specified delay and never again.
+-- | Produce a signal once after the specified delay and never again.
 -- The event's value will be the input signal at that point.
 
-after :: Monad m => Time -> Wire m a (Event a)
+after :: Monad m => Time -> Wire m a a
 after t' =
     mkGen $ \(wsDTime -> dt) x ->
         let t = t' - dt in
         if t <= 0
-          then return (Right (Just x), never)
-          else return (Right Nothing, after t)
+          then return (Right x, never)
+          else return (Left noEvent, after t)
 
 
 -- | Produce an event according to the given list of time deltas and
@@ -83,18 +62,18 @@
 -- produces the event @'a'@ after one second, @'b'@ after three seconds
 -- and @'c'@ after six seconds.
 
-afterEach :: forall a b m. Monad m => [(Time, b)] -> Wire m a (Event b)
+afterEach :: forall a b m. Monad m => [(Time, b)] -> Wire m a b
 afterEach = afterEach' 0
     where
-    afterEach' :: Time -> [(Time, b)] -> Wire m a (Event b)
+    afterEach' :: Time -> [(Time, b)] -> Wire m a b
     afterEach' _ [] = never
     afterEach' t' d@((int, x):ds) =
         mkGen $ \(wsDTime -> dt) _ ->
             let t = t' + dt in
             if t >= int
               then let nextT = t - int
-                   in nextT `seq` return (Right (Just x), afterEach' (t - int) ds)
-              else return (Right Nothing, afterEach' t d)
+                   in nextT `seq` return (Right x, afterEach' (t - int) ds)
+              else return (Left noEvent, afterEach' t d)
 
 
 -- | Event dam.  Collects all values from the input list and emits one
@@ -103,15 +82,15 @@
 -- Note that this combinator can cause event congestion.  If you feed
 -- values faster than it can produce, it will leak memory.
 
-dam :: forall a m. Monad m => Wire m [a] (Event a)
+dam :: forall a m. Monad m => Wire m [a] a
 dam = dam' []
     where
-    dam' :: [a] -> Wire m [a] (Event a)
+    dam' :: [a] -> Wire m [a] a
     dam' xs =
         mkGen $ \_ ys ->
             case xs ++ ys of
-              []        -> return (Right Nothing, dam' [])
-              (ee:rest) -> return (Right (Just ee), dam' rest)
+              []       -> return (Left noEvent, dam' [])
+              (x:rest) -> return (Right x, dam' rest)
 
 
 -- | Delay events by the time interval in the left signal.
@@ -122,19 +101,19 @@
 -- starts to drop), it will leak memory.  Use 'delayEventSafe' to
 -- prevent this.
 
-delayEvents :: forall a m. Monad m => Wire m (Time, Event a) (Event a)
+delayEvents :: forall a m. Monad m => Wire m (Time, Maybe a) a
 delayEvents = delayEvent' Seq.empty 0
     where
-    delayEvent' :: Seq (Time, a) -> Time -> Wire m (Time, Event a) (Event a)
+    delayEvent' :: Seq (Time, a) -> Time -> Wire m (Time, Maybe a) a
     delayEvent' es' t' =
         mkGen $ \(wsDTime -> dt) (int, ev) -> do
             let t = t' + dt
                 es = t `seq` maybe es' (\ee -> es' |> (t + int, ee)) ev
             case Seq.viewl es of
-              Seq.EmptyL -> return (Right Nothing, delayEvent' es 0)
+              Seq.EmptyL -> return (Left noEvent, delayEvent' es 0)
               (et, ee) :< rest
-                  | t >= et   -> return (Right (Just ee), delayEvent' rest t)
-                  | otherwise -> return (Right Nothing, delayEvent' es t)
+                  | t >= et   -> return (Right ee, delayEvent' rest t)
+                  | otherwise -> return (Left noEvent, delayEvent' es t)
 
 
 -- | Delay events by the time interval in the left signal.  The event
@@ -146,66 +125,49 @@
 -- However, if it's decreased below the number of currently queued
 -- events, the events are not deleted.
 
-delayEventsSafe :: forall a m. Monad m => Wire m (Time, Int, Event a) (Event a)
+delayEventsSafe :: forall a m. Monad m => Wire m (Time, Int, Maybe a) a
 delayEventsSafe = delayEventSafe' Seq.empty 0
     where
-    delayEventSafe' :: Seq (Time, a) -> Time -> Wire m (Time, Int, Event a) (Event a)
+    delayEventSafe' :: Seq (Time, a) -> Time -> Wire m (Time, Int, Maybe a) a
     delayEventSafe' es' t' =
         mkGen $ \(wsDTime -> dt) (int, maxEvs, ev') -> do
             let t = t' + dt
                 ev = guard (Seq.length es' < maxEvs) >> ev'
                 es = t `seq` maybe es' (\ee -> es' |> (t + int, ee)) ev
             case Seq.viewl es of
-              Seq.EmptyL -> return (Right Nothing, delayEventSafe' es 0)
+              Seq.EmptyL -> return (Left noEvent, delayEventSafe' es 0)
               (et, ee) :< rest
-                  | t >= et   -> return (Right (Just ee), delayEventSafe' rest t)
-                  | otherwise -> return (Right Nothing, delayEventSafe' es t)
-
-
--- | Decoupled variant of 'hold'.
-
-dHold :: forall a m. Monad m => a -> Wire m (Event a) a
-dHold x0 = dHold'
-    where
-    dHold' :: Wire m (Event a) a
-    dHold' =
-        mkGen $ \_ ->
-            return . maybe (Right x0, dHold') (\x1 -> (Right x0, dHold x1))
+                  | t >= et   -> return (Right ee, delayEventSafe' rest t)
+                  | otherwise -> return (Left noEvent, delayEventSafe' es t)
 
 
 -- | Drop the given number of events, before passing events through.
 
-dropEvents :: forall a m. Monad m => Int -> Wire m (Event a) (Event a)
+dropEvents :: forall a m. Monad m => Int -> Wire m a a
 dropEvents 0 = identity
-dropEvents n = drop'
-    where
-    drop' :: Wire m (Event a) (Event a)
-    drop' =
-        mkGen $ \_ ->
-            return .
-            maybe (Right Nothing, drop')
-                  (const (Right Nothing, dropEvents (pred n)))
+dropEvents n =
+    mkGen $ \_ x -> return (Right x, dropEvents (pred n))
 
 
 -- | Timed event gate for the right signal, which begins closed and
 -- opens after the time interval in the left signal has passed.
 
-dropFor :: forall a m. Monad m => Wire m (Time, Event a) (Event a)
+dropFor :: forall a m. Monad m => Wire m (Time, a) a
 dropFor = dropFor' 0
     where
-    dropFor' :: Time -> Wire m (Time, Event a) (Event a)
+    dropFor' :: Time -> Wire m (Time, a) a
     dropFor' t' =
-        mkGen $ \(wsDTime -> dt) (int, ev) ->
+        mkGen $ \(wsDTime -> dt) (int, x) ->
             let t = t' + dt in
             if t >= int
-              then return (Right ev, arr snd)
-              else return (Right Nothing, dropFor' t)
+              then return (Right x, arr snd)
+              else return (Left noEvent, dropFor' t)
 
 
 -- | Produce a single event with the right signal whenever the left
 -- signal switches from 'False' to 'True'.
 
-edge :: Monad m => Wire m (Bool, a) (Event a)
+edge :: Monad m => Wire m (Bool, a) a
 edge = edgeBy fst snd
 
 
@@ -213,141 +175,113 @@
 -- to 'True' for the input signal, produce an event carrying the value
 -- given by applying the second argument function to the input signal.
 
-edgeBy :: forall a b m. Monad m => (a -> Bool) -> (a -> b) -> Wire m a (Event b)
+edgeBy :: forall a b m. Monad m => (a -> Bool) -> (a -> b) -> Wire m a b
 edgeBy p f = edgeBy'
     where
-    edgeBy' :: Wire m a (Event b)
+    edgeBy' :: Wire m a b
     edgeBy' =
         mkGen $ \_ subject ->
             if p subject
-              then return (Right (Just (f subject)), switchBack)
-              else return (Right Nothing, edgeBy')
+              then return (Right (f subject), switchBack)
+              else return (Left noEvent, edgeBy')
 
-    switchBack :: Wire m a (Event b)
+    switchBack :: Wire m a b
     switchBack =
         mkGen $ \_ subject ->
-            return (Right Nothing, if p subject then switchBack else edgeBy')
+            return (Left noEvent, if p subject then switchBack else edgeBy')
 
 
 -- | Produce a single event carrying the value of the input signal,
 -- whenever the input signal switches to 'Just'.
 
-edgeJust :: Monad m => Wire m (Maybe a) (Event a)
+edgeJust :: Monad m => Wire m (Maybe a) a
 edgeJust = edgeBy isJust fromJust
 
 
--- | Turn discrete events into continuous signals.  Initially produces
--- the argument value.  Each time an event occurs, the produced value is
--- switched to the event's value.
+-- | Variant of 'exhibit', which produces a 'Maybe' instead of an
+-- 'Either'.
+--
+-- Never inhibits.  Same feedback properties as argument wire.
 
-hold :: forall a m. Monad m => a -> Wire m (Event a) a
-hold x0 = hold'
-    where
-    hold' :: Wire m (Event a) a
-    hold' =
-        mkGen $ \_ ->
-            return .
-            maybe (Right x0, hold')
-                  (Right &&& hold)
+event :: Monad m => Wire m a b -> Wire m a (Maybe b)
+event w' =
+    mkGen $ \ws x' -> do
+        (mx, w) <- toGen w' ws x'
+        case mx of
+          Left _  -> return (Right Nothing, event w)
+          Right x -> return (Right (Just x), event w)
 
 
--- | Never produce an event.
+-- | Never produce an event.  This is equivalent to 'inhibit', but with
+-- a contextually more appropriate exception message.
 
-never :: Monad m => Wire m a (Event b)
-never = constant Nothing
+never :: Monad m => Wire m a b
+never = mkGen $ \_ _ -> return (Left noEvent, never)
 
 
 -- | Suppress the first event occurence.
 
-notYet :: Monad m => Wire m (Event a) (Event a)
-notYet = mkGen $ \_ -> return . maybe (Right Nothing, notYet) (const (Right Nothing, identity))
+notYet :: Monad m => Wire m a a
+notYet = mkGen $ \_ _ -> return (Left noEvent, identity)
 
 
 -- | Produce an event at the first instant and never again.
 
-now :: Monad m => b -> Wire m a (Event b)
-now x = constantAfter Nothing (Just x)
-
-
--- | Pass the first event occurence through and suppress all future
--- events.
-
-once :: Monad m => Wire m (Event a) (Event a)
-once =
-    mkGen $ \_ ev ->
-        case ev of
-          Nothing -> return (Right Nothing, once)
-          Just _  -> return (Right ev, constant Nothing)
+once :: Monad m => Wire m a a
+once = mkGen $ \_ x -> return (Right x, never)
 
 
 -- | Emit the right signal event each time the left signal interval
 -- passes.
 
-repeatedly :: forall a m. Monad m => Wire m (Time, a) (Event a)
+repeatedly :: forall a m. Monad m => Wire m (Time, a) a
 repeatedly = repeatedly' 0
     where
-    repeatedly' :: Time -> Wire m (Time, a) (Event a)
+    repeatedly' :: Time -> Wire m (Time, a) a
     repeatedly' t' =
         mkGen $ \(wsDTime -> dt) (int, x) ->
             let t = t' + dt in
             if t >= int
               then let nextT = fmod t int
-                   in nextT `seq` return (Right (Just x), repeatedly' nextT)
-              else return (Right Nothing, repeatedly' t)
+                   in nextT `seq` return (Right x, repeatedly' nextT)
+              else return (Left noEvent, repeatedly' t)
 
 
 -- | Each time the signal interval passes emit the next element from the
 -- given list.
 
-repeatedlyList :: forall a m. Monad m => [a] -> Wire m Time (Event a)
+repeatedlyList :: forall a m. Monad m => [a] -> Wire m Time a
 repeatedlyList = repeatedly' 0
     where
-    repeatedly' :: Time -> [a] -> Wire m Time (Event a)
-    repeatedly' _ [] = constant Nothing
+    repeatedly' :: Time -> [a] -> Wire m Time a
+    repeatedly' _ [] = never
     repeatedly' t' x@(x0:xs) =
         mkGen $ \(wsDTime -> dt) int ->
             let t = t' + dt in
             if t >= int
               then let nextT = fmod t int
-                   in nextT `seq` return (Right (Just x0), repeatedly' nextT xs)
-              else return (Right Nothing, repeatedly' t x)
+                   in nextT `seq` return (Right x0, repeatedly' nextT xs)
+              else return (Left noEvent, repeatedly' t x)
 
 
 -- | Pass only the first given number of events.  Then suppress events
 -- forever.
 
-takeEvents :: forall a m. Monad m => Int -> Wire m (Event a) (Event a)
-takeEvents 0 = constant Nothing
-takeEvents n = take'
-    where
-    take' :: Wire m (Event a) (Event a)
-    take' =
-        mkGen $ \_ ev ->
-            case ev of
-              Nothing -> return (Right Nothing, take')
-              Just _  -> return (Right ev, takeEvents (pred n))
+takeEvents :: forall a m. Monad m => Int -> Wire m a a
+takeEvents 0 = never
+takeEvents n = mkGen $ \_ x -> return (Right x, takeEvents (pred n))
 
 
 -- | Timed event gate for the right signal, which starts open and slams
 -- shut after the left signal time interval passed.
 
-takeFor :: forall a m. Monad m => Wire m (Time, Event a) (Event a)
+takeFor :: forall a m. Monad m => Wire m (Time, a) a
 takeFor = takeFor' 0
     where
-    takeFor' :: Time -> Wire m (Time, Event a) (Event a)
+    takeFor' :: Time -> Wire m (Time, a) a
     takeFor' t' =
-        mkGen $ \(wsDTime -> dt) (int, ev) ->
+        mkGen $ \(wsDTime -> dt) (int, x) ->
             let t = t' + dt in
             if t >= int
-              then return (Right Nothing, constant Nothing)
-              else return (Right ev, takeFor' t)
-
-
--- | Inhibit the signal, unless an event occurs.
-
-wait :: Monad m => Wire m (Event a) a
-wait =
-    mkGen $ \_ ev ->
-        case ev of
-          Nothing -> return (Left (inhibitEx "Waiting for event"), wait)
-          Just ee -> return (Right ee, wait)
+              then return (Left noEvent, never)
+              else return (Right x, takeFor' t)
diff --git a/FRP/NetWire/IO.hs b/FRP/NetWire/IO.hs
--- a/FRP/NetWire/IO.hs
+++ b/FRP/NetWire/IO.hs
@@ -9,7 +9,6 @@
 module FRP.NetWire.IO
     ( -- * IO Actions
       execute,
-      executeEvery,
       executeOnce
     )
     where
@@ -25,34 +24,17 @@
 --
 -- Note: If the action throws an exception, then this wire inhibits the
 -- signal.
+--
+-- Inhibits on exception.  No feedback.
 
 execute :: MonadControlIO m => Wire m (m a) a
-execute =
-    mkGen $ \_ c -> liftM (, execute) (try c)
-
-
--- | Executes the IO action in the right input signal periodically
--- keeping its most recent result value.
-
-executeEvery :: forall a m. MonadControlIO m => Wire m (Time, m a) a
-executeEvery = executeEvery' True 0 (Left (inhibitEx "No result yet."))
-    where
-    executeEvery' :: Bool -> Time -> Output a -> Wire m (Time, m a) a
-    executeEvery' firstRun t' mx' =
-        mkGen $ \(wsDTime -> dt) (int, c) ->
-            let t = t' + dt in
-            if t >= int || firstRun
-              then do
-                  let nextT = fmod t int
-                  mx <- nextT `seq` try c
-                  case mx of
-                    Left _  -> return (mx', executeEvery' False nextT mx')
-                    Right _ -> return (mx, executeEvery' False nextT mx)
-              else return (mx', executeEvery' False t mx')
+execute = mkGen $ \_ c -> liftM (, execute) (try c)
 
 
 -- | Executes the IO action in the input signal and inhibits, until it
 -- succeeds without an exception.  Keeps the result forever.
+--
+-- Inhibits until the first result value.  No feedback.
 
 executeOnce :: MonadControlIO m => Wire m (m a) a
 executeOnce =
diff --git a/FRP/NetWire/Random.hs b/FRP/NetWire/Random.hs
--- a/FRP/NetWire/Random.hs
+++ b/FRP/NetWire/Random.hs
@@ -28,12 +28,16 @@
 
 
 -- | Impure noise between 0 (inclusive) and 1 (exclusive).
+--
+-- Never inhibits.
 
 noise :: MonadIO m => Wire m a Double
 noise = noiseGen
 
 
 -- | Impure noise between -1 (inclusive) and 1 (exclusive).
+--
+-- Never inhibits.
 
 noise1 :: MonadIO m => Wire m a Double
 noise1 =
@@ -43,6 +47,8 @@
 
 
 -- | Impure noise.
+--
+-- Never inhibits.
 
 noiseGen :: (MonadIO m, MTRandom b) => Wire m a b
 noiseGen =
@@ -52,19 +58,23 @@
 
 
 -- | Impure noise between 0 (inclusive) and the input signal
--- (exclusive).  Note:  The noise is generated by multiplying a
+-- (exclusive).  Note:  The noise is generated by multiplying with a
 -- 'Double', hence the precision is limited.
+--
+-- Never inhibits.  Feedback by delay.
 
 noiseR :: (MonadIO m, Real a, Integral b) => Wire m a b
 noiseR =
     mkGen $ \(wsRndGen -> mt) n -> do
         x' <- liftIO (random mt)
         let x = floor ((x' :: Double) * realToFrac n)
-        x `seq` return (Right x, noiseR)
+        return (Right x, noiseR)
 
 
 -- | Pure noise.  For impure wires it's recommended to use the impure
 -- noise generators.
+--
+-- Never inhibits.
 
 pureNoise :: (Monad m, R.RandomGen g, R.Random b) => g -> Wire m a b
 pureNoise g' =
@@ -75,15 +85,19 @@
 
 -- | Pure noise in a range.  For impure wires it's recommended to use
 -- the impure noise generators.
+--
+-- Never inhibits.  Feedback by delay.
 
 pureNoiseR :: (Monad m, R.RandomGen g, R.Random b) => g -> Wire m (b, b) b
 pureNoiseR g' =
     mkGen $ \_ range ->
         let (x, g) = R.randomR range g'
-        in x `seq` return (Right x, pureNoise g)
+        in return (Right x, pureNoise g)
 
 
 -- | Impure random boolean.
+--
+-- Never inhibits.
 
 wackelkontakt :: MonadIO m => Wire m a Bool
 wackelkontakt = noiseGen
diff --git a/FRP/NetWire/Request.hs b/FRP/NetWire/Request.hs
--- a/FRP/NetWire/Request.hs
+++ b/FRP/NetWire/Request.hs
@@ -18,6 +18,8 @@
 
 
 -- | Choose a unique identifier when switching in and keep it.
+--
+-- Never inhibits.
 
 identifier :: MonadIO m => Wire m a Int
 identifier =
diff --git a/FRP/NetWire/Session.hs b/FRP/NetWire/Session.hs
--- a/FRP/NetWire/Session.hs
+++ b/FRP/NetWire/Session.hs
@@ -19,40 +19,53 @@
 
 import Control.Applicative
 import Control.Concurrent.STM
-import Control.Exception
+import Control.Exception.Control
+import Control.Monad.IO.Class
+import Control.Monad.IO.Control
 import Data.IORef
 import Data.Time.Clock
 import FRP.NetWire.Wire
 
 
--- | Reactive sessions with the given time type.
+-- | Reactive sessions with the given input and output types over the
+-- given monad.  The monad must have a 'MonadControlIO' instance to be
+-- usable with the stepping functions.
 
-data Session a b =
+data Session m a b =
     Session {
-      sessFreeVar  :: TVar Bool,             -- ^ False, if in use.
-      sessStateRef :: IORef (WireState IO),  -- ^ State of the last instant.
-      sessTimeRef  :: IORef UTCTime,         -- ^ Time of the last instant.
-      sessWireRef  :: IORef (Wire IO a b)    -- ^ Wire for the next instant.
+      sessFreeVar  :: TVar Bool,            -- ^ False, if in use.
+      sessStateRef :: IORef (WireState m),  -- ^ State of the last instant.
+      sessTimeRef  :: IORef UTCTime,        -- ^ Time of the last instant.
+      sessWireRef  :: IORef (Wire m a b)    -- ^ Wire for the next instant.
     }
 
 
 -- | Feed the given input value into the reactive system performing the
 -- next instant using real time.
 
-stepWire :: a -> Session a b -> IO (Output b)
+stepWire ::
+    MonadControlIO m
+    => a              -- ^ Input value.
+    -> Session m a b  -- ^ Session to step.
+    -> m (Output b)   -- ^ System's output.
 stepWire x' sess =
     withBlock sess $ do
-        t <- getCurrentTime
+        t <- liftIO getCurrentTime
         stepWireTime' t x' sess
 
 
 -- | Feed the given input value into the reactive system performing the
 -- next instant using the given time delta.
 
-stepWireDelta :: NominalDiffTime -> a -> Session a b -> IO (Output b)
+stepWireDelta ::
+    MonadControlIO m
+    => NominalDiffTime  -- ^ Time delta.
+    -> a                -- ^ Input value.
+    -> Session m a b    -- ^ Session to step.
+    -> m (Output b)     -- ^ System's output.
 stepWireDelta dt x' sess =
     withBlock sess $ do
-        t' <- readIORef (sessTimeRef sess)
+        t' <- liftIO (readIORef $ sessTimeRef sess)
         let t@(UTCTime td tt) = addUTCTime dt t'
         td `seq` tt `seq` t `seq` stepWireTime' t x' sess
 
@@ -61,55 +74,76 @@
 -- next instant, which is at the given time.  This function is
 -- thread-safe.
 
-stepWireTime :: UTCTime -> a -> Session a b -> IO (Output b)
+stepWireTime ::
+    MonadControlIO m
+    => UTCTime        -- ^ Absolute time of the instant to perform.
+    -> a              -- ^ Input value.
+    -> Session m a b  -- ^ Session to step.
+    -> m (Output b)   -- ^ System's output.
 stepWireTime t' x' sess = withBlock sess (stepWireTime' t' x' sess)
 
 
 -- | Feed the given input value into the reactive system performing the
--- next instant, which is at the given time.  This function is *not*
+-- next instant, which is at the given time.  This function is /not/
 -- thread-safe.
 
-stepWireTime' :: UTCTime -> a -> Session a b -> IO (Output b)
+stepWireTime' ::
+    MonadIO m
+    => UTCTime        -- ^ Absolute time of the instant to perform.
+    -> a              -- ^ Input value.
+    -> Session m a b  -- ^ Session to step.
+    -> m (Output b)   -- ^ System's output.
 stepWireTime' t x' sess = do
     let Session { sessTimeRef = tRef, sessStateRef = wsRef, sessWireRef = wRef
                 } = sess
 
     -- Time delta.
-    t' <- readIORef tRef
+    t' <- liftIO (readIORef tRef)
     let dt = realToFrac (diffUTCTime t t')
-    dt `seq` writeIORef tRef t
+    dt `seq` liftIO (writeIORef tRef t)
 
     -- Wire state.
-    ws' <- readIORef wsRef
+    ws' <- liftIO (readIORef wsRef)
     let ws = ws' { wsDTime = dt }
-    ws `seq` writeIORef wsRef ws
+    ws `seq` liftIO (writeIORef wsRef ws)
 
     -- Wire.
-    w' <- readIORef wRef
+    w' <- liftIO (readIORef wRef)
     (x, w) <- toGen w' ws x'
-    w `seq` writeIORef wRef w
+    w `seq` liftIO (writeIORef wRef w)
 
     return x
 
 
 -- | Perform an interlocked step function.
 
-withBlock :: Session a b -> IO c -> IO c
+withBlock ::
+    MonadControlIO m
+    => Session m a b  -- ^ The session to mark as locked for the
+                      -- duration of the given computation.
+    -> m c            -- ^ Computation to perform.
+    -> m c            -- ^ Result.
 withBlock (Session { sessFreeVar = freeVar }) c = do
-    atomically (readTVar freeVar >>= check >> writeTVar freeVar False)
-    c `finally` atomically (writeTVar freeVar True)
+    liftIO (atomically $ readTVar freeVar >>= check >> writeTVar freeVar False)
+    c `finally` liftIO (atomically $ writeTVar freeVar True)
 
 
 -- | Initialize a reactive session and pass it to the given
 -- continuation.
 
-withWire :: Wire IO a b -> (Session a b -> IO c) -> IO c
+withWire ::
+    MonadControlIO m
+    => Wire m a b              -- ^ Initial wire of the session.
+    -> (Session m a b -> m c)  -- ^ Continuation, which receives the
+                               -- session data.
+    -> m c                     -- ^ Continuation's result.
 withWire w k = do
-    t@(UTCTime td tt) <- getCurrentTime
-    ws <- initWireState
+    t@(UTCTime td tt) <- liftIO getCurrentTime
+    ws <- liftIO initWireState
 
     sess <-
         td `seq` tt `seq` t `seq` ws `seq`
+        liftIO $
         Session
         <$> newTVarIO True
         <*> newIORef ws
@@ -118,4 +152,4 @@
 
     seq sess (k sess)
         `finally`
-        (readIORef (sessStateRef sess) >>= cleanupWireState)
+        (liftIO $ readIORef (sessStateRef sess) >>= cleanupWireState)
diff --git a/FRP/NetWire/Switch.hs b/FRP/NetWire/Switch.hs
--- a/FRP/NetWire/Switch.hs
+++ b/FRP/NetWire/Switch.hs
@@ -35,7 +35,7 @@
     (Applicative m, Monad m, Traversable f) =>
     (forall w. a -> f w -> f (b, w)) ->
     f (Wire m b c) ->
-    Wire m (a, Event (f (Wire m b c) -> f (Wire m b c))) (f c)
+    Wire m (a, Maybe (f (Wire m b c) -> f (Wire m b c))) (f c)
 drpSwitch route wires''' =
     WGen $ \ws (x'', ev) -> do
         let wires'' = route x'' wires'''
@@ -51,7 +51,7 @@
 drpSwitchB ::
     (Applicative m, Monad m, Traversable f) =>
     f (Wire m a b) ->
-    Wire m (a, Event (f (Wire m a b) -> f (Wire m a b))) (f b)
+    Wire m (a, Maybe (f (Wire m a b) -> f (Wire m a b))) (f b)
 drpSwitchB wires'' =
     WGen $ \ws (x', ev) -> do
         r <- T.sequenceA $ fmap (\w' -> toGen w' ws x') wires''
@@ -63,7 +63,7 @@
 
 -- | Decoupled variant of 'rSwitch'.
 
-drSwitch :: Monad m => Wire m a b -> Wire m (a, Event (Wire m a b)) b
+drSwitch :: Monad m => Wire m a b -> Wire m (a, Maybe (Wire m a b)) b
 drSwitch w1' =
     WGen $ \ws (x', swEv) -> do
         (mx, w1) <- toGen w1' ws x'
@@ -73,7 +73,7 @@
 
 -- | Decoupled variant of 'switch'.
 
-dSwitch :: Monad m => Wire m a (b, Event c) -> (c -> Wire m a b) -> Wire m a b
+dSwitch :: Monad m => Wire m a (b, Maybe c) -> (c -> Wire m a b) -> Wire m a b
 dSwitch w1' f =
     WGen $ \ws x' -> do
         (m, w1) <- toGen w1' ws x'
@@ -124,7 +124,7 @@
     (Applicative m, Monad m, Traversable f) =>
     (forall w. a -> f w -> f (b, w)) ->
     f (Wire m b c) ->
-    Wire m (a, Event (f (Wire m b c) -> f (Wire m b c))) (f c)
+    Wire m (a, Maybe (f (Wire m b c) -> f (Wire m b c))) (f c)
 rpSwitch route wires''' =
     WGen $ \ws (x'', ev) -> do
         let wires'' = maybe id id ev wires'''
@@ -144,7 +144,7 @@
 
 rpSwitchB ::
     (Applicative m, Monad m, Traversable f) =>
-    f (Wire m a b) -> Wire m (a, Event (f (Wire m a b) -> f (Wire m a b))) (f b)
+    f (Wire m a b) -> Wire m (a, Maybe (f (Wire m a b) -> f (Wire m a b))) (f b)
 rpSwitchB wires'' =
     WGen $ \ws (x', ev) -> do
         let wires' = maybe id id ev wires''
@@ -158,7 +158,7 @@
 -- switch takes switching events and switches to the wires contained in
 -- the events.  The first argument is the initial wire.
 
-rSwitch :: Monad m => Wire m a b -> Wire m (a, Event (Wire m a b)) b
+rSwitch :: Monad m => Wire m a b -> Wire m (a, Maybe (Wire m a b)) b
 rSwitch w1 =
     WGen $ \ws (x', swEv) -> do
         let w' = maybe w1 id swEv
@@ -173,7 +173,7 @@
 -- event at some point.  When this event is produced, then the signal
 -- path switches to the wire produced by the second argument function.
 
-switch :: Monad m => Wire m a (b, Event c) -> (c -> Wire m a b) -> Wire m a b
+switch :: Monad m => Wire m a (b, Maybe c) -> (c -> Wire m a b) -> Wire m a b
 switch w1' f =
     WGen $ \ws x' -> do
         (m, w1) <- toGen w1' ws x'
diff --git a/FRP/NetWire/Tools.hs b/FRP/NetWire/Tools.hs
--- a/FRP/NetWire/Tools.hs
+++ b/FRP/NetWire/Tools.hs
@@ -16,10 +16,14 @@
       timeFrom,
 
       -- * Signal transformers
+      accum,
+      delay,
       discrete,
+      hold,
       keep,
 
       -- * Inhibitors
+      forbid,
       inhibit,
       require,
 
@@ -33,11 +37,6 @@
       (-=>),
       (>=-),
 
-      -- * Switches
-      -- ** Unconditional switches
-      constantAfter,
-      initially,
-
       -- * Arrow tools
       mapA,
 
@@ -56,17 +55,23 @@
 
 
 -- | Override the output value at the first non-inhibited instant.
+--
+-- Same inhibition properties as argument wire.  Same feedback
+-- properties as argument wire.
 
 (-->) :: Monad m => b -> Wire m a b -> Wire m a b
 y --> w' =
     WGen $ \ws x -> do
         (mx, w) <- toGen w' ws x
         case mx of
-          e@(Left _) -> return (e, y --> w)
-          Right _    -> return (Right y, w)
+          Left _  -> return (mx, y --> w)
+          Right _ -> return (Right y, w)
 
 
 -- | Override the input value, until the wire starts producing.
+--
+-- Same inhibition properties as argument wire.  Same feedback
+-- properties as argument wire.
 
 (>--) :: Monad m => a -> Wire m a b -> Wire m a b
 x' >-- w' =
@@ -77,41 +82,64 @@
 
 -- | Apply a function to the wire's output at the first non-inhibited
 -- instant.
+--
+-- Same inhibition properties as argument wire.  Same feedback
+-- properties as argument wire.
 
 (-=>) :: Monad m => (b -> b) -> Wire m a b -> Wire m a b
 f -=> w' =
     WGen $ \ws x' -> do
         (mx, w) <- toGen w' ws x'
         case mx of
-          e@(Left _) -> return (e, f -=> w)
-          Right x    -> return (Right (f x), w)
+          Left _  -> return (mx, f -=> w)
+          Right x -> return (Right (f x), w)
 
 
 -- | Apply a function to the wire's input, until the wire starts
 -- producing.
+--
+-- Same inhibition properties as argument wire.  Same feedback
+-- properties as argument wire.
 
 (>=-) :: Monad m => (a -> a) -> Wire m a b -> Wire m a b
 f >=- w' =
     WGen $ \ws x' -> do
         (mx, w) <- toGen w' ws (f x')
-        case mx of
-          e@(Left _) -> return (e, f >=- w)
-          Right _    -> return (mx, w)
+        return (mx, either (const (f >=- w)) (const w) mx)
 
 
+-- | This function corresponds to the 'iterate' function for lists.
+-- Begins with an initial output value.  Each time an input function is
+-- received, it is applied to the current accumulator and the new value
+-- is emitted.
+--
+-- Never inhibits.  Direct feedback.
+
+accum :: Monad m => a -> Wire m (a -> a) a
+accum x = mkGen $ \_ f -> x `seq` return (Right x, accum (f x))
+
+
 -- | The constant wire.  Please use this function instead of @arr (const
 -- c)@.
+--
+-- Never inhibits.
 
 constant :: b -> Wire m a b
 constant = WConst
 
 
--- | Produce the value of the second argument at the first instant.
--- Then produce the second value forever.
+-- | One-instant delay.  Delay the signal for an instant returning the
+-- argument value at the first instant.  This wire is mainly useful to
+-- add feedback support to wires, which wouldn't support it by
+-- themselves.  For example, the 'FRP.NetWire.Analyze.avg' wire does not
+-- support feedback by itself, but the following works:
+--
+-- > do rec x <- delay 1 <<< avg 1000 -< x
+--
+-- Never inhibits.  Direct feedback.
 
-constantAfter :: Monad m => b -> b -> Wire m a b
-constantAfter x1 x0 =
-    mkGen $ \_ _ -> return (Right x0, constant x1)
+delay :: Monad m => a -> Wire m a a
+delay r = mkGen $ \_ x -> return (Right r, delay x)
 
 
 -- | Turn a continuous signal into a discrete one.  This transformer
@@ -119,6 +147,8 @@
 --
 -- The interval length is followed in real time.  If it's zero, then
 -- this wire acts like @second id@.
+--
+-- Never inhibits.  Feedback by delay.
 
 discrete :: forall a m. Monad m => Wire m (Time, a) a
 discrete =
@@ -142,7 +172,9 @@
 
 
 -- | This function corresponds to 'try' for exceptions, allowing you to
--- observe inhibited signals.
+-- observe inhibited signals.  See also 'FRP.NetWire.Event.event'.
+--
+-- Never inhibits.  Same feedback properties as argument wire.
 
 exhibit :: Monad m => Wire m a b -> Wire m a (Output b)
 exhibit w' =
@@ -158,12 +190,26 @@
 fmod n d = n - d * realToFrac (floor $ n/d)
 
 
+-- | Inhibit, when the left signal is true.
+--
+-- Inhibits on true left signal.  No feedback.
+
+forbid :: Monad m => Wire m (Bool, a) a
+forbid =
+    mkGen $ \_ (b, x) ->
+        return (if b then Left (inhibitEx "Forbidden condition met") else Right x,
+                forbid)
+
+
 -- | Effectively prevent a wire from rewiring itself.  This function
 -- will turn any stateful wire into a stateless wire, rendering most
 -- wires useless.
 --
 -- Note:  This function should not be used normally.  Use it only, if
 -- you know exactly what you're doing.
+--
+-- Same inhibition properties as first instant of argument wire.  Same
+-- feedback properties as first instant of argument wire.
 
 freeze :: Monad m => Wire m a b -> Wire m a b
 freeze w =
@@ -172,28 +218,49 @@
         return (mx, w)
 
 
+-- | Keep the latest output.
+--
+-- Inhibits until first signal from argument wire.  Same feedback
+-- properties as argument wire.
+
+hold :: forall a b m. Monad m => Wire m a b -> Wire m a b
+hold w' =
+    mkGen $ \ws x' -> do
+        (mx, w) <- toGen w' ws x'
+        case mx of
+          Right x -> return (mx, hold' x w)
+          Left _  -> return (mx, hold w)
+
+    where
+    hold' :: b -> Wire m a b -> Wire m a b
+    hold' x0 w' =
+        mkGen $ \ws x' -> do
+            (mx, w) <- toGen w' ws x'
+            case mx of
+              Left _  -> return (Right x0, hold' x0 w)
+              Right x -> return (Right x, hold' x w)
+
+
 -- | Identity signal transformer.  Outputs its input.
+--
+-- Never inhibits.  Feedback by delay.
 
 identity :: Monad m => Wire m a a
 identity = id
 
 
 -- | Unconditional inhibition with the given inhibition exception.
+--
+-- Always inhibits.
 
 inhibit :: (Exception e, Monad m) => Wire m e b
 inhibit =
     WGen $ \_ ex -> return (Left (toException ex), inhibit)
 
 
--- | Produce the argument value at the first instant.  Then act as the
--- identity signal transformer forever.
-
-initially :: Monad m => a -> Wire m a a
-initially x0 =
-    mkGen $ \_ _ -> return (Right x0, identity)
-
-
 -- | Keep the value in the first instant forever.
+--
+-- Never inhibits.  Feedback by delay.
 
 keep :: Monad m => Wire m a a
 keep = mkGen $ \_ x -> return (Right x, constant x)
@@ -209,7 +276,9 @@
           (x0:xs) -> arr (uncurry (:)) <<< a *** mapA a -< (x0, xs)
 
 
--- | Inhibit right signal, when the left signal is false.
+-- | Inhibit, when the left signal is false.
+--
+-- Inhibits on false left signal.  No feedback.
 
 require :: Monad m => Wire m (Bool, a) a
 require =
@@ -220,10 +289,13 @@
 
 -- | Sample the given wire at specific intervals.  Use this instead of
 -- 'discrete', if you want to prevent the signal from passing through
--- the wire all the time.
+-- the wire all the time.  Returns the most recent result.
 --
 -- The left signal interval is allowed to become zero, at which point
 -- the signal is passed through the wire at every instant.
+--
+-- Inhibits until the first result from the argument wire.  Same
+-- feedback properties as argument wire.
 
 sample :: forall a b m. Monad m => Wire m a b -> Wire m (Time, a) b
 sample w' =
@@ -238,14 +310,18 @@
             let t = t' + dt in
             if t >= int || int <= 0
               then do
-                  (mx, w) <- toGen w' ws x''
-                  let nextT = fmod t int
-                  nextT `seq` return (either (const mx') (const mx) mx, sample' nextT mx' w)
+                  (mmx, w) <- toGen w' (ws { wsDTime = t }) x''
+                  let mx = either (const mx') (const mmx) mmx
+                      nextT = fmod t int
+                  () `seq` return (mx, sample' nextT mx w)
               else
                   return (mx', sample' t mx' w')
 
 
 -- | Wait for the first signal from the given wire and keep it forever.
+--
+-- Inhibits until signal from argument wire.  Direct feedback, if
+-- argument wire never inhibits, otherwise no feedback.
 
 swallow :: Monad m => Wire m a b -> Wire m a b
 swallow w' =
@@ -261,12 +337,16 @@
 
 
 -- | Get the local time.
+--
+-- Never inhibits.
 
 time :: Monad m => Wire m a Time
 time = timeFrom 0
 
 
 -- | Get the local time, assuming it starts from the given value.
+--
+-- Never inhibits.
 
 timeFrom :: Monad m => Time -> Wire m a Time
 timeFrom t' =
diff --git a/FRP/NetWire/Wire.hs b/FRP/NetWire/Wire.hs
--- a/FRP/NetWire/Wire.hs
+++ b/FRP/NetWire/Wire.hs
@@ -12,8 +12,7 @@
       WireState(..),
 
       -- * Auxilliary types
-      Event,
-      InhibitException,
+      InhibitException(..),
       Output,
       SF,
       Time,
@@ -23,6 +22,7 @@
       inhibitEx,
       initWireState,
       mkGen,
+      noEvent,
       toGen
     )
     where
@@ -32,6 +32,8 @@
 import Control.Category
 import Control.Concurrent.STM
 import Control.Exception (Exception(..), SomeException)
+import Control.Monad
+import Control.Monad.Fix
 import Control.Monad.IO.Class
 import Data.Functor.Identity
 import Data.Typeable
@@ -42,7 +44,7 @@
 -- | Events are signals, which can be absent.  They usually denote
 -- discrete occurences of certain events.
 
-type Event = Maybe
+--type Event = Maybe
 
 
 -- | Inhibition exception with an informative message.  This exception
@@ -56,8 +58,7 @@
 instance Exception InhibitException
 
 
--- | The output of a wire.  When the wire inhibits, then this will be a
--- 'Left' value with an exception.
+-- | Functor for output signals.
 
 type Output = Either SomeException
 
@@ -81,36 +82,37 @@
     WId    :: Wire m a a
 
 
+-- | This instance corresponds to the 'ArrowPlus' and 'ArrowZero'
+-- instances.
+
 instance Monad m => Alternative (Wire m a) where
     empty = zeroArrow
     (<|>) = (<+>)
 
 
+-- | Applicative interface to signal networks.
+
 instance Monad m => Applicative (Wire m a) where
     pure = WConst
 
     wf' <*> wx' =
         WGen $ \ws x' -> do
-            (mf, wf) <- toGen wf' ws x'
-            (mx, wx) <- toGen wx' ws x'
-            return (mf <*> mx, wf <*> wx)
+            (cf, wf) <- toGen wf' ws x'
+            (cx, wx) <- toGen wx' ws x'
+            return (cf <*> cx, wf <*> wx)
 
 
+-- | Arrow interface to signal networks.
+
 instance Monad m => Arrow (Wire m) where
     arr = WArr
 
-    first (WGen f) =
-        WGen $ \ws (x', y) -> do
-            (mx, w) <- f ws x'
-            return (fmap (,y) mx, first w)
+    first (WGen f) = WGen $ \ws (x', y) -> liftM (fmap (, y) *** first) (f ws x')
     first (WArr f) = WArr (first f)
     first (WConst c) = WArr (first (const c))
     first WId = WId
 
-    second (WGen f) =
-        WGen $ \ws (x, y') -> do
-            (my, w) <- f ws y'
-            return (fmap (x,) my, second w)
+    second (WGen f) = WGen $ \ws (x, y') -> liftM (fmap (x,) *** second) (f ws y')
     second (WArr f) = WArr (second f)
     second (WConst c) = WArr (second (const c))
     second WId = WId
@@ -119,59 +121,64 @@
     WId *** wg = second wg
     wf' *** wg' =
         WGen $ \ws (x', y') -> do
-            (mx, wf) <- toGen wf' ws x'
-            (my, wg) <- toGen wg' ws y'
-            return (liftA2 (,) mx my, wf *** wg)
+            (cx, wf) <- toGen wf' ws x'
+            (cy, wg) <- toGen wg' ws y'
+            return (liftA2 (,) cx cy, wf *** wg)
 
     wf' &&& wg' =
         WGen $ \ws x' -> do
-            (mx1, wf) <- toGen wf' ws x'
-            (mx2, wg) <- toGen wg' ws x'
-            return (liftA2 (,) mx1 mx2, wf &&& wg)
+            (cx1, wf) <- toGen wf' ws x'
+            (cx2, wg) <- toGen wg' ws x'
+            return (liftA2 (,) cx1 cx2, wf &&& wg)
 
 
+-- | Signal routing.  Unused routes are frozen, until they are put back
+-- into use.
+
 instance Monad m => ArrowChoice (Wire m) where
     left w' = wl
         where
         wl =
             WGen $ \ws mx' ->
                 case mx' of
-                  Left x' -> do
-                      (mx, w) <- toGen w' ws x'
-                      return (fmap Left mx, left w)
-                  Right x -> return (Right (Right x), wl)
+                  Left x' -> liftM (fmap Left *** left) (toGen w' ws x')
+                  Right x -> return (pure (Right x), wl)
 
     right w' = wl
         where
         wl =
             WGen $ \ws mx' ->
                 case mx' of
-                  Right x' -> do
-                      (mx, w) <- toGen w' ws x'
-                      return (fmap Right mx, right w)
-                  Left x -> return (Right (Left x), wl)
+                  Right x' -> liftM (fmap Right *** right) (toGen w' ws x')
+                  Left x   -> return (pure (Left x), wl)
 
     wf' +++ wg' =
         WGen $ \ws mx' ->
             case mx' of
-              Left x' -> do
-                  (mx, wf) <- toGen wf' ws x'
-                  return (fmap Left mx, wf +++ wg')
-              Right x' -> do
-                  (mx, wg) <- toGen wg' ws x'
-                  return (fmap Right mx, wf' +++ wg)
+              Left x'  -> liftM (fmap Left *** (+++ wg')) (toGen wf' ws x')
+              Right x' -> liftM (fmap Right *** (wf' +++)) (toGen wg' ws x')
 
     wf' ||| wg' =
         WGen $ \ws mx' ->
             case mx' of
-              Left x' -> do
-                  (mx, wf) <- toGen wf' ws x'
-                  return (mx, wf ||| wg')
-              Right x' -> do
-                  (mx, wg) <- toGen wg' ws x'
-                  return (mx, wf' ||| wg)
+              Left x'  -> liftM (second (||| wg')) (toGen wf' ws x')
+              Right x' -> liftM (second (wf' |||)) (toGen wg' ws x')
 
 
+-- | Value recursion.  Warning: Recursive signal networks must never
+-- inhibit.  Use 'FRP.NetWire.Tools.exhibit' or 'FRP.NetWire.Event.event'.
+
+instance MonadFix m => ArrowLoop (Wire m) where
+    loop w' =
+        WGen $ \ws x' -> do
+            rec (Right (x, d), w) <- toGen w' ws (x', d)
+            return (Right x, loop w)
+
+
+-- | Left-biased signal network combination.  If the left arrow
+-- inhibits, the right arrow is tried.  If both inhibit, their
+-- combination inhibits.
+
 instance Monad m => ArrowPlus (Wire m) where
     WGen f <+> wg =
         WGen $ \ws x' -> do
@@ -187,12 +194,14 @@
     WId           <+> _ = WId
 
 
+-- | The zero arrow always inhibits.
+
 instance Monad m => ArrowZero (Wire m) where
-    zeroArrow =
-        mkGen $ \_ _ ->
-            return (Left (inhibitEx "Signal inhibited"), zeroArrow)
+    zeroArrow = mkGen $ \_ _ -> return (Left (inhibitEx "Signal inhibited"), zeroArrow)
 
 
+-- | Identity signal network and signal network sequencing.
+
 instance Monad m => Category (Wire m) where
     id = WId
 
@@ -235,6 +244,8 @@
     w1 . WId = w1
 
 
+-- | Map over the result of a signal network.
+
 instance Monad m => Functor (Wire m a) where
     fmap f (WGen w') =
         WGen $ \ws x' -> do
@@ -285,6 +296,13 @@
 
 mkGen :: (WireState m -> a -> m (Output b, Wire m a b)) -> Wire m a b
 mkGen = WGen
+
+
+-- | Construct an 'InhibitException' wrapped in a 'SomeException' with a
+-- message indicating that a certain event did not happen.
+
+noEvent :: SomeException
+noEvent = inhibitEx "No event"
 
 
 -- | Extract the transition function of a wire.
diff --git a/netwire.cabal b/netwire.cabal
--- a/netwire.cabal
+++ b/netwire.cabal
@@ -1,5 +1,5 @@
 Name:          netwire
-Version:       1.1.0
+Version:       1.2.0
 Category:      FRP, Network
 Synopsis:      Arrowized FRP implementation
 Maintainer:    Ertugrul Söylemez <es@ertes.de>
@@ -11,10 +11,10 @@
 Stability:     beta
 Cabal-version: >= 1.8
 Description:
-
     This library provides an arrowized functional reactive programming
-    (FRP) implementation.  It is similar to Yampa and Animas, but has a
-    much simpler internal representation and a lot of new features.
+    (FRP) implementation.  From the basic idea it is similar to Yampa
+    and Animas, but has a much simpler internal representation and a lot
+    of new features.
 
 Library
     Build-depends:
@@ -32,6 +32,7 @@
     Extensions:
         Arrows
         DeriveDataTypeable
+        FlexibleInstances
         GADTs
         RankNTypes
         ScopedTypeVariables
@@ -57,12 +58,12 @@
 -- Executable netwire-test
 --     Build-depends:
 --         base >= 4 && <= 5,
---         gloss,
 --         netwire,
---         time
+--         transformers
 --     Extensions:
---         Arrows,
+--         Arrows
 --         ScopedTypeVariables
+--         ViewPatterns
 --     Hs-Source-Dirs: test
 --     Main-is: Main.hs
 --     GHC-Options: -W -threaded -rtsopts
