diff --git a/FRP/NetWire.hs b/FRP/NetWire.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire.hs
@@ -0,0 +1,45 @@
+-- |
+-- Module:     FRP.NetWire
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Arrowized FRP implementation for networking applications.  The aim of
+-- this library is to provide a convenient FRP implementation, which
+-- should enable you to write entirely pure network sessions.
+
+module FRP.NetWire
+    ( -- * Wires
+      Wire, Time, DTime, Event,
+
+      -- * Reactive sessions
+      Session,
+      stepWire,
+      stepWireDelta,
+      stepWireTime,
+      withWire,
+
+      -- * 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,
+      module FRP.NetWire.Request,
+      module FRP.NetWire.Switch,
+      module FRP.NetWire.Tools
+    )
+    where
+
+import FRP.NetWire.Analyze
+import FRP.NetWire.Calculus
+-- import FRP.NetWire.Concurrent
+import FRP.NetWire.Event
+import FRP.NetWire.IO
+import FRP.NetWire.Random
+import FRP.NetWire.Request
+import FRP.NetWire.Session
+import FRP.NetWire.Switch
+import FRP.NetWire.Tools
+import FRP.NetWire.Wire
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,134 @@
+-- |
+-- Module:     FRP.NetWire.Analyze
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Signal analysis.
+
+module FRP.NetWire.Analyze
+    ( -- * Changes
+      diff,
+
+      -- * Statistics
+      -- ** Average
+      avg,
+      avgAll,
+      avgFps,
+
+      -- ** Peak
+      highPeak,
+      lowPeak,
+      peakBy,
+    )
+    where
+
+import qualified Data.Vector.Unboxed.Mutable as V
+import Control.DeepSeq
+import Data.Vector.Unboxed.Mutable (IOVector, Unbox)
+import FRP.NetWire.Wire
+
+
+-- | Calculate the average of the signal over the given number of last
+-- samples.  This wire has O(n) space complexity and O(1) time
+-- complexity.
+--
+-- If you need an average over all samples ever produced, consider using
+-- 'avgAll' instead.
+
+avg :: forall v. (Fractional v, NFData v, Unbox v) => Int -> Wire v v
+avg n =
+    mkGen $ \_ x -> do
+        samples <- V.replicate n (x/d)
+        return (Just x, avg' samples x 0)
+
+    where
+    avg' :: IOVector v -> v -> Int -> Wire v v
+    avg' samples s' cur' =
+        mkGen $ \_ ((/d) -> x) -> do
+            let cur = let cur = succ cur' in if cur >= n then 0 else cur
+            x' <- V.read samples cur
+            V.write samples cur x
+            let s = s' - x' + x
+            s `deepseq` return (Just s, avg' samples s cur)
+
+    d :: v
+    d = realToFrac n
+
+
+-- | Calculate the average of the signal over all samples.
+--
+-- 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.
+
+avgAll :: forall v. (Fractional v, NFData v) => Wire v v
+avgAll = mkGen $ \_ x -> return (Just x, avgAll' 1 x)
+    where
+    avgAll' :: v -> v -> Wire v v
+    avgAll' n' a' =
+        mkGen $ \_ x ->
+            let n = n' + 1
+                a = a' - a'/n + x/n in
+            n `deepseq` a `deepseq` return (Just a, avgAll' n a)
+
+
+-- | Calculate the average number of frames per virtual second for the
+-- last given number of frames.
+--
+-- Please note that this wire uses the clock, which you give the network
+-- 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.
+
+avgFps :: forall a. Int -> Wire a Double
+avgFps = avgFps' . avg
+    where
+    avgFps' :: Wire Double Double -> Wire a Double
+    avgFps' w' =
+        mkGen $ \ws@(wsDTime -> dt) _ -> do
+            (ma, w) <- toGen w' ws dt
+            return (fmap recip ma, avgFps' w)
+
+
+-- | Emits an event, whenever the input signal changes.  The event
+-- contains the last input value and the time elapsed since the last
+-- change.
+
+diff :: forall a. Eq a => Wire a (Event (a, Time))
+diff =
+    mkGen $ \(wsDTime -> dt) x' ->
+        return (Just Nothing, diff' dt x')
+
+    where
+    diff' :: Time -> a -> Wire a (Event (a, Time))
+    diff' t' x' =
+        mkGen $ \(wsDTime -> dt) x ->
+            let t = t' + dt in
+            if x' == x
+              then return (Just Nothing, diff' t x')
+              else return (Just (Just (x', t)), diff' 0 x)
+
+
+-- | Returh the high peak.
+
+highPeak :: (NFData a, Ord a) => Wire a a
+highPeak = peakBy compare
+
+
+-- | Return the low peak.
+
+lowPeak :: (NFData a, Ord a) => Wire a a
+lowPeak = peakBy (flip compare)
+
+
+-- | Return the high peak with the given comparison function.
+
+peakBy :: forall a. NFData a => (a -> a -> Ordering) -> Wire a a
+peakBy comp = mkGen $ \_ x -> return (Just x, peakBy' x)
+    where
+    peakBy' :: a -> Wire a a
+    peakBy' p' =
+        mkGen $ \_ x -> do
+            let p = if comp x p' == GT then x else p'
+            p `deepseq` return (Just p, peakBy' p)
diff --git a/FRP/NetWire/Calculus.hs b/FRP/NetWire/Calculus.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Calculus.hs
@@ -0,0 +1,45 @@
+-- |
+-- Module:     FRP.NetWire.Calculus
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Calculus functions.
+
+module FRP.NetWire.Calculus
+    ( -- * Calculus over time
+      derivative,
+      derivativeFrom,
+      integral
+    )
+    where
+
+import Control.DeepSeq
+import Data.VectorSpace
+import FRP.NetWire.Wire
+
+
+-- | Differentiate over time.  Inhibits at first instant.
+
+derivative :: (NFData v, VectorSpace v, Scalar v ~ Double) => Wire v v
+derivative = mkGen $ \_ y2 -> return (Nothing, derivativeFrom y2)
+
+
+-- | Differentiate over time.  The argument is the value before the
+-- first instant.
+
+derivativeFrom :: (NFData v, VectorSpace v, Scalar v ~ Double) => v -> Wire v v
+derivativeFrom y1 =
+    mkGen $ \(wsDTime -> dt) y2 -> do
+        let dy = (y2 ^-^ y1) ^/ dt
+        dy `deepseq` return (Just dy, derivativeFrom y2)
+
+
+-- | Integrate over time.  The argument is the integration constant.
+
+integral :: (NFData v, VectorSpace v, Scalar v ~ Double) => v -> Wire v v
+integral x1 =
+    mkGen $ \ws dx -> do
+        let dt = wsDTime ws
+            x2 = x1 ^+^ dt *^ dx
+        x2 `deepseq` return (Just x2, integral x2)
diff --git a/FRP/NetWire/Event.hs b/FRP/NetWire/Event.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Event.hs
@@ -0,0 +1,355 @@
+-- |
+-- Module:     FRP.NetWire.Event
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Events.
+
+module FRP.NetWire.Event
+    ( -- * Producing events
+      after,
+      afterEach,
+      edge,
+      edgeBy,
+      edgeJust,
+      never,
+      now,
+      once,
+      repeatedly,
+      repeatedlyList,
+
+      -- * Wire transformers
+      wait,
+
+      -- * Event transformers
+      -- ** Delaying events
+      dam,
+      delayEvents,
+      delayEventsSafe,
+      -- ** Selecting events
+      dropEvents,
+      dropFor,
+      notYet,
+      takeEvents,
+      takeFor,
+      -- ** Manipulating events
+      accum,
+      -- ** Mapping to continuous signals
+      hold, dHold
+    )
+    where
+
+import qualified Data.Sequence as Seq
+import Control.Arrow
+import Control.Monad
+import Data.Maybe
+import Data.Sequence (Seq, (|>), ViewL((:<)))
+import FRP.NetWire.Tools
+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. a -> Wire (Event (a -> a)) (Event a)
+accum ee' = accum'
+    where
+    accum' :: Wire (Event (a -> a)) (Event a)
+    accum' =
+        mkGen $ \_ ->
+            return .
+            maybe (Nothing, accum')
+                  (\f -> let ee = f ee' in ee `seq` (Just (Just ee), accum ee))
+
+
+-- | Produce an event once after the specified delay and never again.
+-- The event's value will be the input signal at that point.
+
+after :: forall a. DTime -> Wire a (Event a)
+after t' =
+    mkGen $ \(wsDTime -> dt) x ->
+        let t = t' - dt in
+        if t <= 0
+          then return (Just (Just x), never)
+          else return (Nothing, after t)
+
+
+-- | Produce an event according to the given list of time deltas and
+-- event values.  The time deltas are relative to each other, hence from
+-- the perspective of switching in @[(1, 'a'), (2, 'b'), (3, 'c')]@
+-- produces the event @'a'@ after one second, @'b'@ after three seconds
+-- and @'c'@ after six seconds.
+
+afterEach :: forall a b. [(DTime, b)] -> Wire a (Event b)
+afterEach = afterEach' 0
+    where
+    afterEach' :: DTime -> [(DTime, b)] -> Wire a (Event 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 (Just (Just x), afterEach' (t - int) ds)
+              else return (Just Nothing, afterEach' t d)
+
+
+-- | Event dam.  Collects all values from the input list and emits one
+-- value at each instant.
+--
+-- Note that this combinator can cause event congestion.  If you feed
+-- values faster than it can produce, it will leak memory.
+
+dam :: forall a. Wire [a] (Event a)
+dam = dam' []
+    where
+    dam' :: [a] -> Wire [a] (Event a)
+    dam' xs =
+        mkGen $ \_ ys ->
+            case xs ++ ys of
+              []        -> return (Just Nothing, dam' [])
+              (ee:rest) -> return (Just (Just ee), dam' rest)
+
+
+-- | Delay events by the time interval in the left signal.
+--
+-- Note that this event transformer has to keep all delayed events in
+-- memory, which can cause event congestion.  If events are fed in
+-- faster than they can be produced (for example when the framerate
+-- starts to drop), it will leak memory.  Use 'delayEventSafe' to
+-- prevent this.
+
+delayEvents :: Wire (DTime, Event a) (Event a)
+delayEvents = delayEvent' Seq.empty 0
+    where
+    delayEvent' :: Seq (DTime, a) -> Time -> Wire (DTime, Event a) (Event 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 (Nothing, delayEvent' es 0)
+              (et, ee) :< rest
+                  | t >= et   -> return (Just (Just ee), delayEvent' rest t)
+                  | otherwise -> return (Just Nothing, delayEvent' es t)
+
+
+-- | Delay events by the time interval in the left signal.  The event
+-- queue is limited to the maximum number of events given by middle
+-- signal.  If the current queue grows to this size, then temporarily no
+-- further events are queued.
+--
+-- As suggested by the type, this maximum can change over time.
+-- However, if it's decreased below the number of currently queued
+-- events, the events are not deleted.
+
+delayEventsSafe :: Wire (DTime, Int, Event a) (Event a)
+delayEventsSafe = delayEventSafe' Seq.empty 0
+    where
+    delayEventSafe' :: Seq (DTime, a) -> Time -> Wire (DTime, Int, Event a) (Event 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 (Nothing, delayEventSafe' es 0)
+              (et, ee) :< rest
+                  | t >= et   -> return (Just (Just ee), delayEventSafe' rest t)
+                  | otherwise -> return (Just Nothing, delayEventSafe' es t)
+
+
+-- | Decoupled variant of 'hold'.
+
+dHold :: forall a. a -> Wire (Event a) a
+dHold x0 = dHold'
+    where
+    dHold' :: Wire (Event a) a
+    dHold' =
+        mkGen $ \_ ->
+            return . maybe (Just x0, dHold') (\x1 -> (Just x0, dHold x1))
+
+
+-- | Drop the given number of events, before passing events through.
+
+dropEvents :: forall a. Int -> Wire (Event a) (Event a)
+dropEvents 0 = identity
+dropEvents n = drop'
+    where
+    drop' :: Wire (Event a) (Event a)
+    drop' =
+        mkGen $ \_ ->
+            return .
+            maybe (Nothing, drop')
+                  (const (Nothing, 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. Wire (DTime, Event a) (Event a)
+dropFor = dropFor' 0
+    where
+    dropFor' :: Time -> Wire (DTime, Event a) (Event a)
+    dropFor' t' =
+        mkGen $ \(wsDTime -> dt) (int, ev) ->
+            let t = t' + dt in
+            if t >= int
+              then return (Just ev, arr snd)
+              else return (Just Nothing, dropFor' t)
+
+
+-- | Produce a single event with the right signal whenever the left
+-- signal switches from 'False' to 'True'.
+
+edge :: Wire (Bool, a) (Event a)
+edge = edgeBy fst snd
+
+
+-- | Whenever the predicate in the first argument switches from 'False'
+-- 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. (a -> Bool) -> (a -> b) -> Wire a (Event b)
+edgeBy p f = edgeBy'
+    where
+    edgeBy' :: Wire a (Event b)
+    edgeBy' =
+        mkGen $ \_ subject ->
+            if p subject
+              then return (Just (Just (f subject)), switchBack)
+              else return (Just Nothing, edgeBy')
+
+    switchBack :: Wire a (Event b)
+    switchBack =
+        mkGen $ \_ subject ->
+            if p subject
+              then return (Just Nothing, switchBack)
+              else return (Just Nothing, edgeBy')
+
+
+-- | Produce a single event carrying the value of the input signal,
+-- whenever the input signal switches to 'Just'.
+
+edgeJust :: Wire (Maybe a) (Event 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.
+
+hold :: forall a. a -> Wire (Event a) a
+hold x0 = hold'
+    where
+    hold' :: Wire (Event a) a
+    hold' =
+        mkGen $ \_ ->
+            return .
+            maybe (Just x0, hold')
+                  (\x -> (Just x, hold x))
+
+
+-- | Never produce an event.
+
+never :: Wire a (Event b)
+never = constant Nothing
+
+
+-- | Suppress the first event occurence.
+
+notYet :: Wire (Event a) (Event a)
+notYet = mkGen $ \_ -> return . maybe (Just Nothing, notYet) (const (Just Nothing, identity))
+
+
+-- | Produce an event at the first instant and never again.
+
+now :: b -> Wire a (Event b)
+now x = constantAfter Nothing (Just x)
+
+
+-- | Pass the first event occurence through and suppress all future
+-- events.
+
+once :: Wire (Event a) (Event a)
+once =
+    mkGen $ \_ ev ->
+        case ev of
+          Nothing -> return (Just Nothing, once)
+          Just _  -> return (Just ev, constant Nothing)
+
+
+-- | Emit the right signal event each time the left signal interval
+-- passes.
+
+repeatedly :: forall a. Wire (DTime, a) (Event a)
+repeatedly = repeatedly' 0
+    where
+    repeatedly' :: Time -> Wire (DTime, a) (Event 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 (Just (Just x), repeatedly' nextT)
+              else return (Just Nothing, repeatedly' t)
+
+
+-- | Each time the signal interval passes emit the next element from the
+-- given list.
+
+repeatedlyList :: forall a. [a] -> Wire DTime (Event a)
+repeatedlyList = repeatedly' 0
+    where
+    repeatedly' :: DTime -> [a] -> Wire DTime (Event a)
+    repeatedly' _ [] = constant Nothing
+    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 (Just (Just x0), repeatedly' nextT xs)
+              else return (Just Nothing, repeatedly' t x)
+
+
+-- | Pass only the first given number of events.  Then suppress events
+-- forever.
+
+takeEvents :: Int -> Wire (Event a) (Event a)
+takeEvents 0 = constant Nothing
+takeEvents n = take'
+    where
+    take' :: Wire (Event a) (Event a)
+    take' =
+        mkGen $ \_ ev ->
+            case ev of
+              Nothing -> return (Just Nothing, take')
+              Just _  -> return (Just ev, takeEvents (pred n))
+
+
+-- | Timed event gate for the right signal, which starts open and slams
+-- shut after the left signal time interval passed.
+
+takeFor :: Wire (DTime, Event a) (Event a)
+takeFor = takeFor' 0
+    where
+    takeFor' :: Time -> Wire (DTime, Event a) (Event a)
+    takeFor' t' =
+        mkGen $ \(wsDTime -> dt) (int, ev) ->
+            let t = t' + dt in
+            if t >= int
+              then return (Just Nothing, constant Nothing)
+              else return (Just ev, takeFor' t)
+
+
+-- | Inhibit the signal, unless an event occurs.
+
+wait :: Wire (Event a) a
+wait =
+    mkGen $ \_ ev ->
+        case ev of
+          Nothing -> return (Nothing, wait)
+          Just _  -> return (ev, wait)
diff --git a/FRP/NetWire/IO.hs b/FRP/NetWire/IO.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/IO.hs
@@ -0,0 +1,67 @@
+-- |
+-- Module:     FRP.NetWire.IO
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Access the rest of the universe.
+
+module FRP.NetWire.IO
+    ( -- * IO Actions
+      execute,
+      executeEvery,
+      executeOnce
+    )
+    where
+
+import Control.Exception
+import FRP.NetWire.Tools
+import FRP.NetWire.Wire
+
+
+-- | Execute the IO action in the input signal at every instant.
+--
+-- Note: If the action throws an exception, then this wire inhibits the
+-- signal.
+
+execute :: Wire (IO a) a
+execute =
+    mkGen $ \_ c -> do
+        mx <- try c
+        case mx of
+          Left (_ :: SomeException) -> return (Nothing, execute)
+          Right x                   -> return (Just x, execute)
+
+
+-- | Executes the IO action in the right input signal periodically
+-- keeping its most recent result value.
+
+executeEvery :: forall a. Wire (DTime, IO a) a
+executeEvery = executeEvery' True 0 Nothing
+    where
+    executeEvery' :: Bool -> Time -> Maybe a -> Wire (DTime, IO 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 (_ :: SomeException) -> return (mx', executeEvery' False nextT mx')
+                    Right x ->
+                        let mx = Just x
+                        in mx `seq` return (mx, executeEvery' False nextT mx)
+              else return (mx', executeEvery' False t mx')
+
+
+-- | Executes the IO action in the input signal and inhibits, until it
+-- succeeds without an exception.  Keeps the result forever.
+
+executeOnce :: Wire (IO a) a
+executeOnce =
+    mkGen $ \_ c -> do
+        mx <- try c
+        case mx of
+          Left (_ :: SomeException) -> return (Nothing, executeOnce)
+          Right x                   -> return (Just x, constant x)
diff --git a/FRP/NetWire/Random.hs b/FRP/NetWire/Random.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Random.hs
@@ -0,0 +1,60 @@
+-- |
+-- Module:     FRP.NetWire.Random
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Noise generators.
+
+module FRP.NetWire.Random
+    ( -- * Noise generators
+      noise,
+      noise1,
+      noiseGen,
+      noiseR,
+      wackelkontakt
+    )
+    where
+
+import FRP.NetWire.Wire
+import System.Random.Mersenne
+
+
+-- | Noise between 0 (inclusive) and 1 (exclusive).
+
+noise :: Wire a Double
+noise = noiseGen
+
+
+-- | Noise between -1 and 1 exclusive.
+
+noise1 :: Wire a Double
+noise1 =
+    mkGen $ \(wsRndGen -> mt) _ -> do
+        x <- fmap (pred . (2*)) $ random mt
+        x `seq` return (Just x, noise1)
+
+
+-- | Noise.
+
+noiseGen :: MTRandom b => Wire a b
+noiseGen =
+    mkGen $ \(wsRndGen -> mt) _ -> do
+        x <- random mt
+        x `seq` return (Just x, noiseGen)
+
+
+-- | Noise between 0 (inclusive) and the input signal (exclusive).
+
+noiseR :: (Real a, Integral b) => Wire a b
+noiseR =
+    mkGen $ \(wsRndGen -> mt) n -> do
+        x' <- random mt
+        let x = floor ((x' :: Double) * realToFrac n)
+        x `seq` return (Just x, noiseR)
+
+
+-- | Random boolean.
+
+wackelkontakt :: Wire a Bool
+wackelkontakt = noiseGen
diff --git a/FRP/NetWire/Request.hs b/FRP/NetWire/Request.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Request.hs
@@ -0,0 +1,30 @@
+-- |
+-- Module:     FRP.NetWire.Request
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Unique identifiers.
+
+module FRP.NetWire.Request
+    ( -- * Identifiers.
+      identifier
+    )
+    where
+
+import Control.Concurrent.STM
+import FRP.NetWire.Wire
+
+
+-- | Choose a unique identifier when switching in and keep it.
+
+identifier :: Wire a Int
+identifier =
+    mkGen $ \ws _ -> do
+        let reqVar = wsReqVar ws
+        req <- atomically $ do
+                   req' <- readTVar reqVar
+                   let req = succ req'
+                   req `seq` writeTVar reqVar (succ req')
+                   return req'
+        return (Just req, WConst req)
diff --git a/FRP/NetWire/Session.hs b/FRP/NetWire/Session.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Session.hs
@@ -0,0 +1,121 @@
+-- |
+-- Module:     FRP.NetWire.Session
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Wire sessions.
+
+module FRP.NetWire.Session
+    ( -- * Sessions
+      Session(..),
+      stepWire,
+      stepWireDelta,
+      stepWireTime,
+      stepWireTime',
+      withWire
+    )
+    where
+
+import Control.Applicative
+import Control.Concurrent.STM
+import Control.Exception
+import Data.IORef
+import Data.Time.Clock
+import FRP.NetWire.Wire
+
+
+-- | Reactive sessions with the given time type.
+
+data Session a b =
+    Session {
+      sessFreeVar  :: TVar Bool,        -- ^ False, if in use.
+      sessStateRef :: IORef WireState,  -- ^ State of the last instant.
+      sessTimeRef  :: IORef UTCTime,    -- ^ Time of the last instant.
+      sessWireRef  :: IORef (Wire 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 (Maybe b)
+stepWire x' sess =
+    withBlock sess $ do
+        t <- 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 (Maybe b)
+stepWireDelta dt x' sess =
+    withBlock sess $ do
+        t' <- readIORef (sessTimeRef sess)
+        let t@(UTCTime td tt) = addUTCTime dt t'
+        td `seq` tt `seq` t `seq` 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
+-- thread-safe.
+
+stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)
+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*
+-- thread-safe.
+
+stepWireTime' :: UTCTime -> a -> Session a b -> IO (Maybe b)
+stepWireTime' t x' sess = do
+    let Session { sessTimeRef = tRef, sessStateRef = wsRef, sessWireRef = wRef
+                } = sess
+
+    -- Time delta.
+    t' <- readIORef tRef
+    let dt = realToFrac (diffUTCTime t t')
+    dt `seq` writeIORef tRef t
+
+    -- Wire state.
+    ws' <- readIORef wsRef
+    let ws = ws' { wsDTime = dt }
+    ws `seq` writeIORef wsRef ws
+
+    -- Wire.
+    w' <- readIORef wRef
+    (x, w) <- toGen w' ws x'
+    w `seq` writeIORef wRef w
+
+    return x
+
+
+-- | Perform an interlocked step function.
+
+withBlock :: Session a b -> IO c -> IO c
+withBlock (Session { sessFreeVar = freeVar }) c = do
+    atomically (readTVar freeVar >>= check >> writeTVar freeVar False)
+    c `finally` atomically (writeTVar freeVar True)
+
+
+-- | Initialize a reactive session and pass it to the given
+-- continuation.
+
+withWire :: Wire a b -> (Session a b -> IO c) -> IO c
+withWire w k = do
+    t@(UTCTime td tt) <- getCurrentTime
+    ws <- initWireState
+
+    sess <-
+        td `seq` tt `seq` t `seq` ws `seq`
+        Session
+        <$> newTVarIO True
+        <*> newIORef ws
+        <*> newIORef t
+        <*> newIORef w
+
+    seq sess (k sess)
+        `finally`
+        (readIORef (sessStateRef sess) >>= cleanupWireState)
diff --git a/FRP/NetWire/Switch.hs b/FRP/NetWire/Switch.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Switch.hs
@@ -0,0 +1,184 @@
+-- |
+-- Module:     FRP.NetWire.Switch
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- Switching combinators.  Note that 'Wire' also provides a
+-- state-preserving 'Control.Arrow.ArrowApply' instance, which may be
+-- more convenient than these combinators in many cases.
+
+module FRP.NetWire.Switch
+    ( -- * Basic switches
+      switch, dSwitch,
+      rSwitch, drSwitch,
+
+      -- * Broadcasters
+      parB,
+      rpSwitchB, drpSwitchB,
+
+      -- * Routers
+      par,
+      rpSwitch, drpSwitch
+    )
+    where
+
+import qualified Data.Traversable as T
+import Data.Traversable (Traversable)
+import FRP.NetWire.Wire
+
+
+-- | Decoupled variant of 'rpSwitch'.
+
+drpSwitch ::
+    Traversable f =>
+    (forall w. a -> f w -> f (b, w)) ->
+    f (Wire b c) ->
+    Wire (a, Event (f (Wire b c) -> f (Wire b c))) (f c)
+drpSwitch route wires''' =
+    WGen $ \ws (x'', ev) -> do
+        let wires'' = route x'' wires'''
+        r <- T.sequenceA $ fmap (\(x', w') -> toGen w' ws x') wires''
+        let xs = T.sequenceA . fmap fst $ r
+            wires' = fmap snd r
+            wires = maybe id id ev wires'
+        return (xs, rpSwitch route wires)
+
+
+-- | Decoupled variant of 'rpSwitchB'.
+
+drpSwitchB ::
+    forall a b f. Traversable f =>
+    f (Wire a b) ->
+    Wire (a, Event (f (Wire a b) -> f (Wire a b))) (f b)
+drpSwitchB wires'' =
+    WGen $ \ws (x', ev) -> do
+        r <- T.sequenceA $ fmap (\w' -> toGen w' ws x') wires''
+        let xs = T.sequenceA . fmap fst $ r
+            wires' = fmap snd r
+            wires = maybe id id ev wires'
+        return (xs, rpSwitchB wires)
+
+
+-- | Decoupled variant of 'rSwitch'.
+
+drSwitch :: Wire a b -> Wire (a, Event (Wire a b)) b
+drSwitch w1' =
+    WGen $ \ws (x', swEv) -> do
+        (mx, w1) <- toGen w1' ws x'
+        let w = maybe w1 id swEv
+        w `seq` return (mx, drSwitch w)
+
+
+-- | Decoupled variant of 'switch'.
+
+dSwitch :: Wire a (b, Event c) -> (c -> Wire a b) -> Wire a b
+dSwitch w1' f =
+    WGen $ \ws x' -> do
+        (m, w1) <- toGen w1' ws x'
+        case m of
+          Nothing        -> return (Nothing, dSwitch w1 f)
+          Just (x, swEv) ->
+              case swEv of
+                Nothing -> return (Just x, dSwitch w1 f)
+                Just sw -> return (Just x, f sw)
+
+
+-- | Route signal to a collection of signal functions using the supplied
+-- routing function.  If any of the wires inhibits, the whole network
+-- inhibits.
+
+par ::
+    Traversable f =>
+    (forall w. a -> f w -> f (b, w)) -> f (Wire b c) -> Wire a (f c)
+par route wires'' =
+    WGen $ \ws x'' -> do
+        let wires' = route x'' wires''
+        r <- T.sequenceA $ fmap (\(x', w') -> toGen w' ws x') wires'
+        let xs = T.sequenceA . fmap fst $ r
+            wires = fmap snd r
+        return (xs, par route wires)
+
+
+-- | Broadcast signal to a collection of signal functions.  If any of
+-- the wires inhibits, then the whole parallel network inhibits.
+
+parB :: Traversable f => f (Wire a b) -> Wire a (f b)
+parB wires' =
+    WGen $ \ws x' -> do
+        r <- T.sequenceA $ fmap (\w' -> toGen w' ws x') wires'
+        let xs = T.sequenceA . fmap fst $ r
+            wires = fmap snd r
+        return (xs, parB wires)
+
+
+-- | Recurrent parallel routing switch.  This combinator acts like
+-- 'par', but takes an additional event signal, which can transform the
+-- set of wires.  This is the most powerful switch.
+--
+-- Just like 'par' if any of the wires inhibits, the whole network
+-- inhibits.
+
+rpSwitch ::
+    Traversable f =>
+    (forall w. a -> f w -> f (b, w)) ->
+    f (Wire b c) ->
+    Wire (a, Event (f (Wire b c) -> f (Wire b c))) (f c)
+rpSwitch route wires''' =
+    WGen $ \ws (x'', ev) -> do
+        let wires'' = maybe id id ev wires'''
+            wires' = route x'' wires''
+        r <- T.sequenceA $ fmap (\(x', w') -> toGen w' ws x') wires'
+        let xs = T.sequenceA . fmap fst $ r
+            wires = fmap snd r
+        return (xs, rpSwitch route wires)
+
+
+-- | Recurrent parallel broadcast switch.  This combinator acts like
+-- 'parB', but takes an additional event signal, which can transform the
+-- set of wires.
+--
+-- Just like 'parB' if any of the wires inhibits, the whole network
+-- inhibits.
+
+rpSwitchB ::
+    Traversable f =>
+    f (Wire a b) -> Wire (a, Event (f (Wire a b) -> f (Wire a b))) (f b)
+rpSwitchB wires'' =
+    WGen $ \ws (x', ev) -> do
+        let wires' = maybe id id ev wires''
+        r <- T.sequenceA $ fmap (\w' -> toGen w' ws x') wires'
+        let xs = T.sequenceA . fmap fst $ r
+            wires = fmap snd r
+        return (xs, rpSwitchB wires)
+
+
+-- | Combinator for recurrent switches.  The wire produced by this
+-- switch takes switching events and switches to the wires contained in
+-- the events.  The first argument is the initial wire.
+
+rSwitch :: Wire a b -> Wire (a, Event (Wire a b)) b
+rSwitch w1 =
+    WGen $ \ws (x', swEv) -> do
+        let w' = maybe w1 id swEv
+        (mx, w) <- toGen w' ws x'
+        return (mx, rSwitch w)
+
+
+-- | This is the most basic switching combinator.  It is an event-based
+-- one-time switch.
+--
+-- The first argument is the initial wire, which may produce a switching
+-- event at some point.  When this event is produced, then the signal
+-- path switches to the wire produced by the second argument function.
+
+switch :: Wire a (b, Event c) -> (c -> Wire a b) -> Wire a b
+switch w1' f =
+    WGen $ \ws x' -> do
+        (m, w1) <- toGen w1' ws x'
+        case m of
+          Nothing        -> return (Nothing, switch w1 f)
+          Just (x, swEv) ->
+              case swEv of
+                Nothing -> return (Just x, switch w1 f)
+                Just sw -> toGen (f sw) (ws { wsDTime = 0 }) x'
diff --git a/FRP/NetWire/Tools.hs b/FRP/NetWire/Tools.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Tools.hs
@@ -0,0 +1,277 @@
+-- |
+-- Module:     FRP.NetWire.Tools
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- The usual FRP tools you'll want to work with.
+
+module FRP.NetWire.Tools
+    ( -- * Basic utilities
+      constant,
+      identity,
+
+      -- * Time
+      time,
+      timeFrom,
+
+      -- * Signal transformers
+      discrete,
+      keep,
+
+      -- * Inhibitors
+      inhibit,
+      require,
+
+      -- * Wire transformers
+      exhibit,
+      freeze,
+      sample,
+      swallow,
+      (-->),
+      (>--),
+      (-=>),
+      (>=-),
+
+      -- * Switches
+      -- ** Unconditional switches
+      constantAfter,
+      initially,
+
+      -- * Arrow tools
+      mapA,
+
+      -- * Convenience functions
+      dup,
+      fmod,
+      swap
+    )
+    where
+
+import Control.Arrow
+import Control.Category hiding ((.))
+import FRP.NetWire.Wire
+import Prelude hiding (id)
+
+
+-- | Override the output value at the first non-inhibited instant.
+
+(-->) :: b -> Wire a b -> Wire a b
+y --> w' =
+    WGen $ \ws x -> do
+        (mx, w) <- toGen w' ws x
+        case mx of
+          Nothing -> return (Nothing, y --> w)
+          Just _  -> return (Just y, w)
+
+
+-- | Override the input value, until the wire starts producing.
+
+(>--) :: a -> Wire a b -> Wire a b
+x' >-- w' =
+    WGen $ \ws _ -> do
+        (mx, w) <- toGen w' ws x'
+        return (mx, maybe (x' >-- w) (const w) mx)
+
+
+-- | Apply a function to the wire's output at the first non-inhibited
+-- instant.
+
+(-=>) :: (b -> b) -> Wire a b -> Wire a b
+f -=> w' =
+    WGen $ \ws x' -> do
+        (mx, w) <- toGen w' ws x'
+        case mx of
+          Nothing -> return (Nothing, f -=> w)
+          Just x  -> return (Just (f x), w)
+
+
+-- | Apply a function to the wire's input, until the wire starts
+-- producing.
+
+(>=-) :: (a -> a) -> Wire a b -> Wire a b
+f >=- w' =
+    WGen $ \ws x' -> do
+        (mx, w) <- toGen w' ws (f x')
+        case mx of
+          Nothing -> return (Nothing, f >=- w)
+          Just x  -> return (Just x, w)
+
+
+-- | The constant wire.  Please use this function instead of @arr (const
+-- c)@.
+
+constant :: b -> Wire a b
+constant = WConst
+
+
+-- | Produce the value of the second argument at the first instant.
+-- Then produce the second value forever.
+
+constantAfter :: b -> b -> Wire a b
+constantAfter x1 x0 =
+    mkGen $ \_ _ -> return (Just x0, constant x1)
+
+
+-- | Turn a continuous signal into a discrete one.  This transformer
+-- picks values from the right signal at intervals of the left signal.
+--
+-- The interval length is followed in real time.  If it's zero, then
+-- this wire acts like @second id@.
+
+discrete :: forall a. Wire (DTime, a) a
+discrete =
+    mkGen $ \(wsDTime -> dt) (_, x0) ->
+        return (Just x0, discrete' dt x0)
+
+    where
+    discrete' :: Time -> a -> Wire (DTime, a) a
+    discrete' t' x' =
+        mkGen $ \(wsDTime -> dt) (int, x) ->
+            let t = t' + dt in
+            if t >= int
+              then return (Just x, discrete' (fmod t int) x)
+              else return (Just x', discrete' t x')
+
+
+-- | Duplicate a value to a tuple.
+
+dup :: a -> (a, a)
+dup x = (x, x)
+
+
+-- | This function corresponds to 'try' for exceptions, allowing you to
+-- observe inhibited signals.
+
+exhibit :: Wire a b -> Wire a (Maybe b)
+exhibit w' =
+    WGen $ \ws x' -> do
+        (mx, w) <- toGen w' ws x'
+        return (Just mx, exhibit w)
+
+
+-- | Floating point modulo operation.  Note that @fmod n 0@ = 0.
+
+fmod :: Double -> Double -> Double
+fmod _ 0 = 0
+fmod n d = n - d * realToFrac (floor $ n/d)
+
+
+-- | 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.
+
+freeze :: Wire a b -> Wire a b
+freeze w =
+    WGen $ \ws x' -> do
+        (mx, _) <- toGen w ws x'
+        return (mx, w)
+
+
+-- | Identity signal transformer.  Outputs its input.
+
+identity :: Wire a a
+identity = id
+
+
+-- | Unconditional inhibition.  Equivalent to 'zeroArrow'.
+
+inhibit :: Wire a b
+inhibit = zeroArrow
+
+
+-- | Produce the argument value at the first instant.  Then act as the
+-- identity signal transformer forever.
+
+initially :: a -> Wire a a
+initially x0 =
+    mkGen $ \_ _ -> return (Just x0, identity)
+
+
+-- | Keep the value in the first instant forever.
+
+keep :: Wire a a
+keep = mkGen $ \_ x -> return (Just x, constant x)
+
+
+-- | Apply an arrow to a list of inputs.
+
+mapA :: ArrowChoice a => a b c -> a [b] [c]
+mapA a =
+    proc x ->
+        case x of
+          [] -> returnA -< []
+          (x0:xs) -> arr (uncurry (:)) <<< a *** mapA a -< (x0, xs)
+
+
+-- | Inhibit right signal, when the left signal is false.
+
+require :: Wire (Bool, a) a
+require =
+    mkGen $ \_ (b, x) ->
+        return (if b then Just x else Nothing, require)
+
+
+-- | 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 left signal interval is allowed to become zero, at which point
+-- the signal is passed through the wire at every instant.
+
+sample :: Wire a b -> Wire (DTime, a) b
+sample w' =
+    WGen $ \ws@(wsDTime -> dt) (_, x') -> do
+        (mx, w) <- toGen w' ws x'
+        return (mx, sample' dt mx w)
+
+    where
+    sample' :: Time -> Maybe b -> Wire a b -> Wire (DTime, a) b
+    sample' t' mx' w' =
+        WGen $ \ws@(wsDTime -> dt) (int, x'') ->
+            let t = t' + dt in
+            if t >= int || int <= 0
+              then do
+                  (mx, w) <- toGen w' ws x''
+                  let nextT = fmod t int
+                  case mx of
+                    Nothing -> nextT `seq` return (mx', sample' nextT mx' w)
+                    Just _  -> nextT `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.
+
+swallow :: Wire a b -> Wire a b
+swallow w' =
+    WGen $ \ws x' -> do
+        (mx, w) <- toGen w' ws x'
+        case mx of
+          Nothing -> return (Nothing, swallow w)
+          Just x  -> do
+              return (Just x, constant x)
+
+
+-- | Swap the values in a tuple.
+
+swap :: (a, b) -> (b, a)
+swap (x, y) = (y, x)
+
+
+-- | Get the local time.
+
+time :: Wire a Time
+time = timeFrom 0
+
+
+-- | Get the local time, assuming it starts from the given value.
+
+timeFrom :: Time -> Wire a Time
+timeFrom t' =
+    mkGen $ \ws _ ->
+        let t = t' + wsDTime ws
+        in t `seq` return (Just t, timeFrom t)
diff --git a/FRP/NetWire/Wire.hs b/FRP/NetWire/Wire.hs
new file mode 100644
--- /dev/null
+++ b/FRP/NetWire/Wire.hs
@@ -0,0 +1,264 @@
+-- |
+-- Module:     FRP.NetWire.Wire
+-- Copyright:  (c) 2011 Ertugrul Soeylemez
+-- License:    BSD3
+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>
+--
+-- The module contains the main 'Wire' type.
+
+module FRP.NetWire.Wire
+    ( -- * Wires
+      Wire(..),
+      WireState(..),
+
+      -- * Auxilliary types
+      DTime,
+      Event,
+      Time,
+
+      -- * Utilities
+      cleanupWireState,
+      initWireState,
+      mkGen,
+      toGen
+    )
+    where
+
+import Control.Applicative
+import Control.Arrow
+import Control.Category
+import Control.Concurrent.STM
+import Prelude hiding ((.), id)
+import System.Random.Mersenne
+
+
+-- | Derivative of time.  In English:  It's the time between two
+-- instants of an FRP session.
+
+type DTime = Double
+
+
+-- | Events are signals, which can be absent.  They usually denote
+-- discrete occurences of certain events.
+
+type Event = Maybe
+
+
+-- | Time.
+
+type Time = Double
+
+
+-- | A wire is a network of signal transformers.
+
+data Wire a b where
+    WArr   :: (a -> b) -> Wire a b
+    WConst :: b -> Wire a b
+    WGen   :: (WireState -> a -> IO (Maybe b, Wire a b)) -> Wire a b
+    WId    :: Wire a a
+
+
+instance Alternative (Wire a) where
+    empty = zeroArrow
+    (<|>) = (<+>)
+
+
+instance Applicative (Wire 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)
+
+
+instance Arrow Wire where
+    arr = WArr
+
+    first (WGen f) =
+        WGen $ \ws (x', y) -> do
+            (mx, w) <- f ws x'
+            return (fmap (,y) mx, first w)
+    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 (WArr f) = WArr (second f)
+    second (WConst c) = WArr (second (const c))
+    second WId = WId
+
+    wf *** WId = first wf
+    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)
+
+    wf' &&& wg' =
+        WGen $ \ws x' -> do
+            (mx1, wf) <- toGen wf' ws x'
+            (mx2, wg) <- toGen wg' ws x'
+            return (liftA2 (,) mx1 mx2, wf &&& wg)
+
+
+instance ArrowChoice Wire 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 (Just (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 (Just (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)
+
+    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)
+
+
+instance ArrowPlus Wire where
+    WGen f <+> wg =
+        WGen $ \ws x' -> do
+            (mx, w1) <- f ws x'
+            case mx of
+              Just _  -> return (mx, w1 <+> wg)
+              Nothing -> do
+                  (mx2, w2) <- toGen wg ws x'
+                  return (mx2, w1 <+> w2)
+
+    wf <+> WGen _ = WGen (toGen wf)
+
+    wa@(WArr _)   <+> _ = wa
+    wc@(WConst _) <+> _ = wc
+    WId           <+> _ = WId
+
+
+instance ArrowZero Wire where
+    zeroArrow = mkGen $ \_ _ -> return (Nothing, zeroArrow)
+
+
+instance Category Wire where
+    id = WId
+
+    -- Combining two general wires.
+    wf@(WGen f) . WGen g =
+        WGen $ \ws x'' -> do
+            (mx', w1) <- g ws x''
+            case mx' of
+              Nothing -> return (Nothing, wf . w1)
+              Just x' -> do
+                  (mx, w2) <- f ws x'
+                  return (mx, w2 . w1)
+
+    -- Combining a special wire with a general wire.
+    wf@(WArr f) . WGen g =
+        WGen $ \ws x' -> do
+            (mx, w) <- g ws x'
+            return (fmap f mx, wf . w)
+    wc@(WConst c) . WGen g =
+        WGen $ \ws x' -> do
+            (mx, w) <- g ws x'
+            return (fmap (const c) mx, wc . w)
+    WGen f . wg@(WArr g) =
+        WGen $ \ws x' -> do
+            (mx, w) <- f ws (g x')
+            return (mx, w . wg)
+    WGen f . wc@(WConst c) =
+        WGen $ \ws _ -> do
+            (mx, w) <- f ws c
+            return (mx, w . wc)
+
+    -- Combining special wires.
+    WArr f . WArr g = WArr (f . g)
+    WArr f . WConst c = WArr (const (f c))
+
+    WConst c . WArr _ = WConst c
+    WConst c . WConst _ = WConst c
+
+    WId . w2 = w2
+    w1 . WId = w1
+
+
+instance Functor (Wire a) where
+    fmap f (WGen w') =
+        WGen $ \ws x' -> do
+            (x, w) <- w' ws x'
+            return (fmap f x, fmap f w)
+    fmap f (WArr g) = WArr (f . g)
+    fmap f (WConst c) = WConst (f c)
+    fmap f WId = WArr f
+
+
+-- | The state of the wire.
+
+data WireState =
+    WireState {
+      wsDTime  :: Double,   -- ^ Time difference for current instant.
+      wsRndGen :: MTGen,    -- ^ Random number generator.
+      wsReqVar :: TVar Int  -- ^ Request counter.
+    }
+
+
+-- | Clean up wire state.
+
+cleanupWireState :: WireState -> IO ()
+cleanupWireState _ = return ()
+
+
+-- | Initialize wire state.
+
+initWireState :: IO WireState
+initWireState =
+    WireState
+    <$> pure 0
+    <*> getStdGen
+    <*> newTVarIO 0
+
+
+-- | Create a generic wire from the given function.  This is a smart
+-- constructor.  Please use it instead of the 'WGen' constructor.
+
+mkGen :: (WireState -> a -> IO (Maybe b, Wire a b)) -> Wire a b
+mkGen = WGen
+
+
+-- | Extract the transition function of a wire.
+
+toGen :: Wire a b -> WireState -> a -> IO (Maybe b, Wire a b)
+toGen (WGen f)      ws x = f ws x
+toGen wf@(WArr f)   _  x = return (Just (f x), wf)
+toGen wc@(WConst c) _  _ = return (Just c, wc)
+toGen wi@WId        _  x = return (Just x, wi)
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,32 @@
+netwire license
+Copyright (c) 2011, Ertugrul Soeylemez
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+
+    * Neither the name of the author nor the names of any contributors
+      may be used to endorse or promote products derived from this
+      software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,12 @@
+Netwire setup script
+Copyright (C) 2011, Ertugrul Soeylemez
+
+Please see the LICENSE file for terms and conditions of use,
+modification and distribution of this package, including this file.
+
+> module Main where
+>
+> import Distribution.Simple
+>
+> main :: IO ()
+> main = defaultMain
diff --git a/netwire.cabal b/netwire.cabal
new file mode 100644
--- /dev/null
+++ b/netwire.cabal
@@ -0,0 +1,62 @@
+Name:          netwire
+Version:       1.0.0
+Category:      FRP, Network
+Synopsis:      Arrowized FRP implementation
+Maintainer:    Ertugrul Söylemez <es@ertes.de>
+Author:        Ertugrul Söylemez <es@ertes.de>
+Copyright:     (c) 2011 Ertugrul Söylemez
+License:       BSD3
+License-file:  LICENSE
+Build-type:    Simple
+Stability:     experimental
+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.
+
+Library
+    Build-depends:
+        base >= 4 && <= 5,
+        containers >= 0.4.0,
+        deepseq >= 1.1.0,
+        mersenne-random >= 1.0.0,
+        stm >= 2.2.0,
+        time >= 1.2.0,
+        vector >= 0.7.1,
+        vector-space >= 0.7.3
+    Extensions:
+        Arrows
+        GADTs
+        RankNTypes
+        ScopedTypeVariables
+        TupleSections
+        TypeFamilies
+        ViewPatterns
+    GHC-Options: -W
+    Exposed-modules:
+        FRP.NetWire
+        FRP.NetWire.Analyze
+        FRP.NetWire.Calculus
+        -- FRP.NetWire.Concurrent
+        FRP.NetWire.Event
+        FRP.NetWire.IO
+        FRP.NetWire.Random
+        FRP.NetWire.Request
+        FRP.NetWire.Session
+        FRP.NetWire.Switch
+        FRP.NetWire.Tools
+        FRP.NetWire.Wire
+
+-- Executable netwire-test
+--     Build-depends:
+--         base >= 4 && <= 5,
+--         netwire,
+--         time
+--     Extensions:
+--         Arrows,
+--         ScopedTypeVariables
+--     Hs-Source-Dirs: test
+--     Main-is: Main.hs
+--     GHC-Options: -W -threaded -rtsopts
