diff --git a/FRP/NetWire.hs b/FRP/NetWire.hs
--- a/FRP/NetWire.hs
+++ b/FRP/NetWire.hs
@@ -11,6 +11,7 @@
 module FRP.NetWire
     ( -- * Wires
       Wire, Output, Time,
+      WireState(..),
       mkGen, toGen,
 
       -- * Reactive sessions
@@ -20,6 +21,10 @@
       stepWireTime,
       withWire,
 
+      -- * Testing wires
+      testWire,
+      testWireStr,
+
       -- * Pure wires
       SF,
       stepSF,
@@ -33,7 +38,6 @@
       -- * Netwire Reexports
       module FRP.NetWire.Analyze,
       module FRP.NetWire.Calculus,
-      module FRP.NetWire.Concurrent,
       module FRP.NetWire.Event,
       module FRP.NetWire.IO,
       module FRP.NetWire.Random,
@@ -53,7 +57,6 @@
 import Data.Functor.Identity
 import FRP.NetWire.Analyze
 import FRP.NetWire.Calculus
-import FRP.NetWire.Concurrent
 import FRP.NetWire.Event
 import FRP.NetWire.IO
 import FRP.NetWire.Pure
diff --git a/FRP/NetWire/Concurrent.hs b/FRP/NetWire/Concurrent.hs
deleted file mode 100644
--- a/FRP/NetWire/Concurrent.hs
+++ /dev/null
@@ -1,91 +0,0 @@
--- |
--- Module:     FRP.NetWire.Concurrent
--- Copyright:  (c) 2011 Ertugrul Soeylemez
--- License:    BSD3
--- Maintainer: Ertugrul Soeylemez <es@ertes.de>
---
--- Wire concurrency.  Send signals through multiple wires concurrently.
--- This module is *highly experimental* and subject to change entirely
--- in future revisions.  Please use it with care.
-
-module FRP.NetWire.Concurrent
-    ( -- * Combining wires
-      (~*~),
-      (~&~),
-      (~+~)
-    )
-    where
-
-import Control.Applicative
-import Control.Arrow
-import Control.Concurrent
-import Control.Concurrent.STM
-import Control.DeepSeq
-import FRP.NetWire.Tools
-import FRP.NetWire.Wire
-
-
--- | 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)
-w1' ~*~ w2' =
-    mkGen $ \ws (x', y') -> do
-        (xVar, thr1) <- forkWire w1' ws x'
-        (yVar, thr2) <- forkWire w2' ws y'
-        (mx, w1) <- takeMVar xVar
-        (my, w2) <- takeMVar yVar
-        mapM_ killThread [thr1, thr2]
-        return (liftA2 (,) mx my, w1 ~*~ w2)
-
-infixr 3 ~*~
-
-
--- | 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)
-w1' ~&~ w2' = arr dup >>> w1' ~*~ w2'
-
-infixr 3 ~&~
-
-
--- | Concurrent version of '<+>'.  Passes its input signal to both
--- argument wires concurrently, returning the result of the first wire
--- which does not inhibit.
-
-(~+~) :: NFData b => Wire IO a b -> Wire IO a b -> Wire IO a b
-w1' ~+~ w2' =
-    mkGen $ \ws x' -> do
-        x1Var <- newEmptyTMVarIO
-        x2Var <- newEmptyTMVarIO
-        thr1 <- forkIO (toGen w1' ws x' >>= atomically . putTMVar x1Var)
-        thr2 <- forkIO (toGen w2' ws x' >>= atomically . putTMVar x2Var)
-        let res1 = do (mx, w1) <- takeTMVar x1Var; check (isRight mx); return (mx, w1 ~+~ w2')
-            res2 = do (mx, w2) <- takeTMVar x2Var; check (isRight mx); return (mx, w1' ~+~ w2)
-            noRes = do (mx1, w1) <- takeTMVar x1Var
-                       (mx2, w2) <- takeTMVar x2Var
-                       check (isLeft mx1 && isLeft mx2)
-                       return (mx2, w1 ~+~ w2)
-        atomically (res1 <|> res2 <|> noRes) <* mapM_ killThread [thr1, thr2]
-
-
--- | Pass the given input to the given wire concurrently.
-
-forkWire :: Wire IO a b -> WireState IO -> a -> IO (MVar (Output b, Wire IO a b), ThreadId)
-forkWire w' ws x' = do
-    resultVar <- newEmptyMVar
-    thr <- forkIO (toGen w' ws x' >>= putMVar resultVar)
-    return (resultVar, thr)
-
-
--- | Is this a left value?
-
-isLeft :: Either e a -> Bool
-isLeft = either (const True) (const False)
-
-
--- | Is this a right value?
-
-isRight :: Either e a -> Bool
-isRight = either (const False) (const True)
diff --git a/FRP/NetWire/Session.hs b/FRP/NetWire/Session.hs
--- a/FRP/NetWire/Session.hs
+++ b/FRP/NetWire/Session.hs
@@ -15,6 +15,10 @@
       stepWireTime',
       withWire,
 
+      -- * Testing wires
+      testWire,
+      testWireStr,
+
       -- * Low level
       sessionStart,
       sessionStop
@@ -22,13 +26,16 @@
     where
 
 import Control.Applicative
+import Control.Arrow
 import Control.Concurrent.STM
 import Control.Exception.Control
+import Control.Monad
 import Control.Monad.IO.Class
 import Control.Monad.IO.Control
 import Data.IORef
 import Data.Time.Clock
 import FRP.NetWire.Wire
+import System.IO
 
 
 -- | Reactive sessions with the given input and output types over the
@@ -143,6 +150,49 @@
     w `seq` liftIO (writeIORef wRef w)
 
     return x
+
+
+-- | Interface to 'testWireStr' accepting all 'Show' instances as the
+-- output type.
+
+testWire ::
+    forall a b m. (MonadControlIO m, Show b)
+    => Int         -- ^ Show output once each this number of frames.
+    -> m a         -- ^ Input generator.
+    -> Wire m a b  -- ^ Your wire.
+    -> m ()
+testWire fpp getInput w' = testWireStr fpp getInput (w' >>> arr show)
+
+
+-- | This function provides a convenient way to test wires.  It wraps a
+-- default loop around your wire, which just displays the output on your
+-- stdout in a single line (it uses an ANSI escape sequence to clear the
+-- line).  It uses real time.
+
+testWireStr ::
+    forall a m. MonadControlIO m
+    => Int              -- ^ Show output once each this number of frames.
+    -> m a              -- ^ Input generator.
+    -> Wire m a String  -- ^ Wire to evolve.
+    -> m ()
+testWireStr fpp getInput w' =
+    withWire w' (loop 0)
+
+    where
+    loop :: Int -> Session m a String -> m ()
+    loop n' sess = do
+        let n = let n = succ n' in if n >= fpp then 0 else n
+
+        x' <- getInput
+        mx <- stepWire x' sess
+        when (n' == 0) . liftIO $ do
+            putStr "\r\027[K"
+            case mx of
+              Left ex   -> putStr (show ex)
+              Right str -> putStr str
+            hFlush stdout
+
+        n `seq` loop n sess
 
 
 -- | Perform an interlocked step function.
diff --git a/FRP/NetWire/Switch.hs b/FRP/NetWire/Switch.hs
--- a/FRP/NetWire/Switch.hs
+++ b/FRP/NetWire/Switch.hs
@@ -19,7 +19,12 @@
 
       -- * Routers
       par,
-      rpSwitch, drpSwitch
+      rpSwitch, drpSwitch,
+
+      -- * Embedding wires
+      appEvent,
+      appFirst,
+      appFrozen
     )
     where
 
diff --git a/FRP/NetWire/Tools.hs b/FRP/NetWire/Tools.hs
--- a/FRP/NetWire/Tools.hs
+++ b/FRP/NetWire/Tools.hs
@@ -202,9 +202,8 @@
 
 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)
+    mkFix $ \_ (b, x) ->
+        return (if b then Left (inhibitEx "Forbidden condition met") else Right x)
 
 
 -- | Inhibit, when the signal is true.
@@ -213,9 +212,8 @@
 
 forbid_ :: Monad m => Wire m Bool ()
 forbid_ =
-    mkGen $ \_ b ->
-        return (if b then Left (inhibitEx "Forbidden condition met") else Right (),
-                forbid_)
+    mkFix $ \_ b ->
+        return (if b then Left (inhibitEx "Forbidden condition met") else Right ())
 
 
 -- | Effectively prevent a wire from rewiring itself.  This function
@@ -230,9 +228,9 @@
 
 freeze :: Monad m => Wire m a b -> Wire m a b
 freeze w =
-    WGen $ \ws x' -> do
+    mkFix $ \ws x' -> do
         (mx, _) <- toGen w ws x'
-        return (mx, w)
+        return mx
 
 
 -- | Keep the latest output.
@@ -272,7 +270,7 @@
 
 inhibit :: (Exception e, Monad m) => Wire m e b
 inhibit =
-    WGen $ \_ ex -> return (Left (toException ex), inhibit)
+    mkFix $ \_ ex -> return (Left (toException ex))
 
 
 -- | Unconditional inhibition with default inhibition exception.
@@ -288,7 +286,7 @@
 -- Inhibits on 'Left' signals.
 
 inject :: forall a e m. (Exception e, Monad m) => Wire m (Either e a) a
-inject = mkGen $ \_ mx -> return (leftToEx mx, inject)
+inject = mkFix $ \_ mx -> return (leftToEx mx)
     where
     leftToEx :: Either e a -> Either SomeException a
     leftToEx (Right x) = Right x
@@ -301,9 +299,8 @@
 
 injectMaybe :: Monad m => Wire m (Maybe a) a
 injectMaybe =
-    mkGen $ \_ mx ->
-        return (maybe (Left (inhibitEx "No signal to inject")) Right mx,
-                injectMaybe)
+    mkFix $ \_ mx ->
+        return (maybe (Left (inhibitEx "No signal to inject")) Right mx)
 
 
 -- | Keep the value in the first instant forever.
@@ -330,9 +327,8 @@
 
 require :: Monad m => Wire m (Bool, a) a
 require =
-    mkGen $ \_ (b, x) ->
-        return (if b then Right x else Left (inhibitEx "Required condition not met"),
-                require)
+    mkFix $ \_ (b, x) ->
+        return (if b then Right x else Left (inhibitEx "Required condition not met"))
 
 
 -- | Inhibit, when the signal is false.
@@ -341,9 +337,8 @@
 
 require_ :: Monad m => Wire m Bool ()
 require_ =
-    mkGen $ \_ b ->
-        return (if b then Right () else Left (inhibitEx "Required condition not met"),
-                require_)
+    mkFix $ \_ b ->
+        return (if b then Right () else Left (inhibitEx "Required condition not met"))
 
 
 -- | Sample the given wire at specific intervals.  Use this instead of
diff --git a/FRP/NetWire/Wire.hs b/FRP/NetWire/Wire.hs
--- a/FRP/NetWire/Wire.hs
+++ b/FRP/NetWire/Wire.hs
@@ -4,7 +4,9 @@
 -- License:    BSD3
 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>
 --
--- The module contains the main 'Wire' type.
+-- The module contains the main 'Wire' type and its type class
+-- instances.  It also provides convenience functions for wire
+-- developers.
 
 module FRP.NetWire.Wire
     ( -- * Wires
@@ -21,9 +23,15 @@
       cleanupWireState,
       inhibitEx,
       initWireState,
+      mkFix,
       mkGen,
       noEvent,
-      toGen
+      toGen,
+
+      -- * Wire transformers
+      appEvent,
+      appFirst,
+      appFrozen
     )
     where
 
@@ -70,8 +78,8 @@
 -- | A wire is a network of signal transformers.
 
 data Wire :: (* -> *) -> * -> * -> * where
-    WArr   :: (a -> b) -> Wire m a b
-    WGen   :: (WireState m -> a -> m (Output b, Wire m a b)) -> Wire m a b
+    WArr :: (a -> b) -> Wire m a b
+    WGen :: (WireState m -> a -> m (Output b, Wire m a b)) -> Wire m a b
 
 
 -- | This instance corresponds to the 'ArrowPlus' and 'ArrowZero'
@@ -104,9 +112,18 @@
     (&&&) = wboth 0
 
 
--- | Signal routing.  Unused routes are frozen, until they are put back
--- into use.
+-- | The 'app' combinator has the behaviour of 'appFrozen'.  Note that
+-- this effectively keeps a wire bound by the "-<<" syntax from
+-- evolving.  For alternative embedding combinators see also 'appEvent'
+-- and 'appFirst'.
 
+instance Monad m => ArrowApply (Wire m) where
+    app = appFrozen
+
+
+-- | Signal routing.  Unused routes are ignored.  Note that they still
+-- run in real time, i.e. the time deltas passed are accumulated.
+
 instance Monad m => ArrowChoice (Wire m) where
     left w' = wl 0
         where
@@ -161,7 +178,7 @@
 
 -- | Value recursion.  Warning: Recursive signal networks must never
 -- inhibit.  Make use of 'FRP.NetWire.Tools.exhibit' or
--- 'FRP.NetWire.Event.event'.
+-- 'FRP.NetWire.Event.event' for wires that may inhibit.
 
 instance MonadFix m => ArrowLoop (Wire m) where
     loop w' =
@@ -172,7 +189,8 @@
 
 -- | Left-biased signal network combination.  If the left arrow
 -- inhibits, the right arrow is tried.  If both inhibit, their
--- combination inhibits.
+-- combination inhibits.  Ignored wire networks still run in real time,
+-- i.e. passed time deltas are accumulated.
 
 instance Monad m => ArrowPlus (Wire m) where
     wf'@(WGen _) <+> wg' = wl 0 wf' wg'
@@ -193,7 +211,7 @@
 -- | The zero arrow always inhibits.
 
 instance Monad m => ArrowZero (Wire m) where
-    zeroArrow = mkGen $ \_ _ -> return (Left (inhibitEx "Signal inhibited"), zeroArrow)
+    zeroArrow = mkFix $ \_ _ -> return (Left (inhibitEx "Signal inhibited"))
 
 
 -- | Identity signal network and signal network sequencing.
@@ -203,7 +221,7 @@
     (.) = flip (wcompose 0)
 
 
--- | Map over the result of a signal network.
+-- | Map over the output of a signal network.
 
 instance Monad m => Functor (Wire m a) where
     fmap f = (>>> arr f)
@@ -222,6 +240,60 @@
     PureState :: { wsDTime :: Double } -> WireState m
 
 
+-- | Embeds the input wire (left signal) into the network with the given
+-- input signal (right signal).  Each time the input wire is a 'Just',
+-- the current state of the last wire is discarded and the new wire is
+-- evolved instead.  New wires can be generated by an event wire and
+-- catched via 'FRP.NetWire.Event.event'.  The initial wire is given by
+-- the argument.
+--
+-- Inhibits whenever the embedded wire inhibits.  Same feedback
+-- behaviour as the embedded wire.
+
+appEvent ::
+    forall a b m. Monad m
+    => Wire m a b
+    -> Wire m (Maybe (Wire m a b), a) b
+appEvent cw' =
+    mkGen $ \ws (mw, x') -> do
+        let w' = maybe cw' id mw
+        (mx, w) <- toGen w' ws x'
+        return (mx, appEvent w)
+
+
+-- | Embeds the first received input wire (left signal) into the
+-- network, feeding it the right signal.  This wire respects its left
+-- signal only in the first instant, after which it wraps that wire's
+-- evolution.
+--
+-- Inhibits whenever the embedded wire inhibits.  Same feedback
+-- behaviour as the embedded wire.
+
+appFirst :: forall a b m. Monad m => Wire m (Wire m a b, a) b
+appFirst =
+    mkGen $ \ws (w', x') -> do
+        (mx, w) <- toGen w' ws x'
+        return (mx, embed w)
+
+    where
+    embed :: Wire m a b -> Wire m (Wire m a b, a) b
+    embed w' =
+        mkGen $ \ws (_, x') -> do
+            (mx, w) <- toGen w' ws x'
+            return (mx, embed w)
+
+
+-- | Embeds the first instant of the input wire (left signal) into the
+-- network, feeding it the right signal.  This wire respects its left
+-- signal in all instances, such that the embedded wire cannot evolve.
+--
+-- Inhibits whenever the embedded wire inhibits.  Same feedback
+-- behaviour as the embedded wire.
+
+appFrozen :: Monad m => Wire m (Wire m a b, a) b
+appFrozen = mkFix $ \ws (w, x') -> liftM fst (toGen w ws x')
+
+
 -- | Clean up wire state.
 
 cleanupWireState :: WireState m -> IO ()
@@ -244,9 +316,17 @@
     <*> newTVarIO 0
 
 
--- | Create a generic wire from the given function.  This is a smart
--- constructor.  Please use it instead of the 'WGen' constructor.
+-- | Create a fixed wire from the given function.  This is a smart
+-- constructor.  It creates a stateless wire.
 
+mkFix :: Monad m => (WireState m -> a -> m (Output b)) -> Wire m a b
+mkFix f = let w = WGen $ \ws -> liftM (, w) . f ws in w
+
+
+-- | Create a generic (i.e. possibly stateful) wire from the given
+-- function.  This is a smart constructor.  Please use it instead of the
+-- 'WGen' constructor for creating generic wires.
+
 mkGen :: (WireState m -> a -> m (Output b, Wire m a b)) -> Wire m a b
 mkGen = WGen
 
@@ -258,7 +338,9 @@
 noEvent = inhibitEx "No event"
 
 
--- | Extract the transition function of a wire.
+-- | Extract the transition function of a wire.  Unless there is reason
+-- (like optimization) to pattern-match against the 'Wire' constructors,
+-- this function is the recommended way to evolve a wire.
 
 toGen :: Monad m => Wire m a b -> WireState m -> a -> m (Output b, Wire m a b)
 toGen (WGen f)    ws x = f ws x
diff --git a/netwire.cabal b/netwire.cabal
--- a/netwire.cabal
+++ b/netwire.cabal
@@ -1,5 +1,5 @@
 Name:          netwire
-Version:       1.2.6
+Version:       1.2.7
 Category:      FRP, Network
 Synopsis:      Arrowized FRP implementation
 Maintainer:    Ertugrul Söylemez <es@ertes.de>
@@ -21,6 +21,7 @@
         base >= 4 && <= 5,
         containers >= 0.4.0,
         deepseq >= 1.1.0,
+--        forkable-monad >= 0.1.1,
         mersenne-random >= 1.0.0,
         monad-control >= 0.2.0,
         random >= 1.0.0,
@@ -45,7 +46,6 @@
         FRP.NetWire
         FRP.NetWire.Analyze
         FRP.NetWire.Calculus
-        FRP.NetWire.Concurrent
         FRP.NetWire.Event
         FRP.NetWire.IO
         FRP.NetWire.Pure
