diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2009, Patai Gergely
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the author nor the names of its 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.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+
+main = defaultMain
diff --git a/doc/Breakout.html b/doc/Breakout.html
new file mode 100644
--- /dev/null
+++ b/doc/Breakout.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title></title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="generator" content="pandoc" /><link rel="stylesheet" href="hscolour.css" type="text/css" media="all" />
+</head><body><h1 id="elerea-breakout-example">Elerea Breakout example</h1><p>Breakout is one of the simplest test applications that brings up some problems with non-trivial solutions. In particular, there is a circular dependency between the position and the velocity of the ball. The position is the integral of the velocity, while velocity can have instantaneous changes due to collisions, which is a function of the position of the ball and the current state of the field. The field is dynamic, and it also forms a mutual dependency loop with the ball position. On top of these, part of the field (at least if we regard the paddle as part of it) depends on user input, and its effects start propagating in the game state as soon as the ball reaches the level of the paddle.</p><p>Elerea lets us express all these circular dependencies in a natural way, by simply referring to the respective signals by their names. User input is also seen as a signal from inside the reactive part, while the imperative framework is given a sink fuction to update it as needed. Type safety is ensured all the way.</p><img src="Breakout.png" alt="Elerea Breakout in action" /><p>Below follows the full source of the example.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Main</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Concurrent</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>IORef</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Maybe</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>UI</span><span class='hs-varop'>.</span><span class='hs-conid'>GLFW</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>GLFW</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>Rendering</span><span class='hs-varop'>.</span><span class='hs-conid'>OpenGL</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span>
+</pre><h2 id="global-constants">Global constants</h2><p>The dimensions of the ball, which behaves as a rectangle in collision detection, but is drawn as an ellipse.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>ballW</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.04</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-varid'>ballH</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.04</span>
+</pre><p>The initial position and velocity of the ball.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>ballPos0</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>0.4</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-varid'>ballVel0</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>0.4</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0.35</span><span class='hs-layout'>)</span>
+</pre><p>The dimensions and vertical position of the player.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>playerW</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.2</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-varid'>playerH</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.03</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-varid'>playerY</span> <span class='hs-keyglyph'>=</span> <span class='hs-comment'>-</span><span class='hs-varid'>fieldH</span><span class='hs-varop'>+</span><span class='hs-num'>0.01</span>
+</pre><p>The dimensions of the field.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>fieldW</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.8</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-varid'>fieldH</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.5</span>
+</pre><p>The dimensions of each brick.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>brickW</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.05</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-varid'>brickH</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.03</span>
+</pre><p>The starting positions of the bricks. The third element of the triples is the state of the brick. A brick can either be alive or dying. Dying bricks also keep track of their fadeout level.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-keyword'>data</span> <span class='hs-conid'>BrickState</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Live</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Dying</span> <span class='hs-conid'>Double</span> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Eq</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-varid'>brickPos0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>distributeBricks</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>0.7</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-num'>0.1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0.7</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0.4</span><span class='hs-layout'>)</span> <span class='hs-num'>18</span> <span class='hs-num'>10</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>where</span> <span class='hs-varid'>distributeBricks</span> <span class='hs-varid'>xmin</span> <span class='hs-varid'>ymin</span> <span class='hs-varid'>xmax</span> <span class='hs-varid'>ymax</span> <span class='hs-varid'>xn</span> <span class='hs-varid'>yn</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-varid'>xmin</span><span class='hs-varop'>+</span><span class='hs-varid'>xstep</span><span class='hs-varop'>*</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>ymin</span><span class='hs-varop'>+</span><span class='hs-varid'>ystep</span><span class='hs-varop'>*</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-conid'>Live</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span>
+<span class='hs-varop'>&gt;</span>                                                         <span class='hs-varid'>x</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-keyglyph'>[</span><span class='hs-num'>0</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>xn</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-keyglyph'>[</span><span class='hs-num'>0</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>yn</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-keyglyph'>]</span><span class='hs-keyglyph'>]</span>
+<span class='hs-varop'>&gt;</span>               <span class='hs-keyword'>where</span> <span class='hs-varid'>xstep</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>xmax</span><span class='hs-comment'>-</span><span class='hs-varid'>xmin</span><span class='hs-comment'>-</span><span class='hs-varid'>xn</span><span class='hs-varop'>*</span><span class='hs-varid'>brickW</span><span class='hs-layout'>)</span><span class='hs-varop'>/</span><span class='hs-layout'>(</span><span class='hs-varid'>xn</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-varop'>+</span><span class='hs-varid'>brickW</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>ystep</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>ymax</span><span class='hs-comment'>-</span><span class='hs-varid'>ymin</span><span class='hs-comment'>-</span><span class='hs-varid'>yn</span><span class='hs-varop'>*</span><span class='hs-varid'>brickH</span><span class='hs-layout'>)</span><span class='hs-varop'>/</span><span class='hs-layout'>(</span><span class='hs-varid'>yn</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-varop'>+</span><span class='hs-varid'>brickH</span>
+</pre><p>The rate at which a brick fades out. The reciprocal of this value gives the fadeout time in seconds.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>brickFade</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>0.5</span>
+</pre><h2 id="game-logic">Game logic</h2><p>The entry point performs some lightweight initialisation, and defines the two user-driven signals: window size and mouse position. The <code>external</code> function creates the signal and the corresponding sink at the same time.</p><p>When all is done <code>driveNetwork</code> is invoked. It is not a library function, but part of the tiny <code>Utils</code> module .</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>main</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-comment'>-- Creating a window without a depth buffer</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>initialize</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>openWindow</span> <span class='hs-layout'>(</span><span class='hs-conid'>Size</span> <span class='hs-num'>640</span> <span class='hs-num'>480</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>DisplayRGBBits</span> <span class='hs-num'>8</span> <span class='hs-num'>8</span> <span class='hs-num'>8</span><span class='hs-layout'>,</span> <span class='hs-conid'>DisplayAlphaBits</span> <span class='hs-num'>8</span><span class='hs-keyglyph'>]</span> <span class='hs-conid'>Window</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>windowTitle</span> <span class='hs-varop'>$=</span> <span class='hs-str'>"Elerea Breakout"</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-comment'>-- External signals available for the game logic</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-layout'>(</span><span class='hs-varid'>windowSize</span><span class='hs-layout'>,</span><span class='hs-varid'>windowSizeSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-varid'>vnull</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-layout'>(</span><span class='hs-varid'>mousePosition</span><span class='hs-layout'>,</span><span class='hs-varid'>mousePositionSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-varid'>vnull</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-comment'>-- Wrapping up the init phase</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>newIORef</span> <span class='hs-conid'>False</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>windowSizeCallback</span> <span class='hs-varop'>$=</span> <span class='hs-varid'>resizeGLScene</span> <span class='hs-varid'>windowSizeSink</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>windowCloseCallback</span> <span class='hs-varop'>$=</span> <span class='hs-varid'>writeIORef</span> <span class='hs-varid'>closed</span> <span class='hs-conid'>True</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>initGL</span> <span class='hs-num'>640</span> <span class='hs-num'>480</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-comment'>-- All we need to get going is an IO-valued signal and an IO</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-comment'>-- function to update the external signals</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>driveNetwork</span> <span class='hs-layout'>(</span><span class='hs-varid'>breakout</span> <span class='hs-varid'>mousePosition</span> <span class='hs-varid'>windowSize</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                <span class='hs-layout'>(</span><span class='hs-varid'>readInput</span> <span class='hs-varid'>mousePositionSink</span> <span class='hs-varid'>closed</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-comment'>-- The inevitable sad ending</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>closeWindow</span>
+</pre><p>The <code>breakout</code> function creates a reactive signal that carries the rendering actions to be performed at each instant. The principal signals forming the game logic are the following:</p><ul><li><code>playerX</code>: the position of the player, a direct function of the mouse position;</li><li><code>ballPos</code>: the position of the ball given as an integral of its velocity, <code>ballVel</code>;</li><li><code>bricks</code>: the collection of live and dying bricks along with collision information.</li></ul><p>The position and velocity of the ball form a circular dependency, as velocity is changed whenever a collision is detected, which is a function of the position.</p><p>The signal carrying the collection of the bricks is obtained by applying a stateful transformation (a transfer function) on the ball position. The state contains the bricks still relevant to the game as well as collision information. Although the latter is technically redundant, it is still worth including here, since it has to be calculated while advancing the state of the bricks, and it is needed elsewhere too.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>breakout</span> <span class='hs-varid'>mousePos</span> <span class='hs-varid'>windowSize</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>renderLevel</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>playerX</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballPos</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>getBricks</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>bricks</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>where</span> 
+</pre><p>User-driven player position:</p><pre><span class='hs-varop'>&gt;</span>           <span class='hs-varid'>playerX</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>adjustPlayerPos</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>mousePos</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>windowSize</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>adjustPlayerPos</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>w</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>min</span> <span class='hs-layout'>(</span><span class='hs-varid'>fieldW</span><span class='hs-comment'>-</span><span class='hs-varid'>playerW</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-varid'>max</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>fieldW</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-num'>2</span><span class='hs-varop'>*</span><span class='hs-varid'>x</span><span class='hs-varop'>/</span><span class='hs-varid'>w</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-comment'>-</span><span class='hs-varid'>playerW</span><span class='hs-varop'>/</span><span class='hs-num'>2</span>
+</pre><p>Ball state: position and velocity. Note the use of the latcher: we wrap a signal created by <code>adjustVel</code> in a <code>pure</code>, hence adding another signal layer around it.</p><pre><span class='hs-varop'>&gt;</span>           <span class='hs-varid'>ballPos</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>integralVec</span> <span class='hs-layout'>(</span><span class='hs-varid'>ballPos0</span><span class='hs-layout'>)</span> <span class='hs-varid'>ballVel</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>ballVel</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>latcher</span> <span class='hs-layout'>(</span><span class='hs-varid'>pure</span> <span class='hs-varid'>ballVel0</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                             <span class='hs-layout'>(</span><span class='hs-varid'>ballCollHorz</span> <span class='hs-varop'>||@</span> <span class='hs-varid'>ballCollVert</span> <span class='hs-varop'>||@</span> <span class='hs-varid'>ballCollPlayer</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                             <span class='hs-layout'>(</span><span class='hs-varid'>pure</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>adjustVel</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>ballCollHorz</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballCollVert</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballCollPlayer</span> <span class='hs-varop'>&lt;*&gt;</span>
+<span class='hs-varop'>&gt;</span>                                        <span class='hs-varid'>ballVel</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballNewVelX</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+</pre><p>The <code>adjustVel</code> function calculates a candidate velocity for the next frame given collision information and the current velocity. Even though it would return the current speed if there are no collisions, we rather not evaluate it at all thanks to the latcher. In the end, velocity is not recalculated in each frame.</p><pre><span class='hs-varop'>&gt;</span>           <span class='hs-varid'>adjustVel</span> <span class='hs-varid'>ch</span> <span class='hs-varid'>cv</span> <span class='hs-varid'>cp</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>bvx</span> <span class='hs-varid'>bvy</span><span class='hs-layout'>)</span> <span class='hs-varid'>bvx'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span>
+<span class='hs-varop'>&gt;</span>               <span class='hs-keyword'>where</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-keyword'>if</span> <span class='hs-varid'>ch</span> <span class='hs-keyword'>then</span> <span class='hs-comment'>-</span><span class='hs-num'>1</span> <span class='hs-keyword'>else</span> <span class='hs-num'>1</span><span class='hs-layout'>)</span><span class='hs-varop'>*</span><span class='hs-layout'>(</span><span class='hs-keyword'>if</span> <span class='hs-varid'>cp</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>bvx'</span><span class='hs-varop'>*</span><span class='hs-num'>4</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>bvx</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>y</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>cv</span> <span class='hs-varop'>||</span> <span class='hs-varid'>cp</span> <span class='hs-keyword'>then</span> <span class='hs-comment'>-</span><span class='hs-varid'>bvy</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>bvy</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>ballNewVelX</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>getX</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>ballPos</span><span class='hs-layout'>)</span><span class='hs-comment'>-</span><span class='hs-varid'>playerX</span><span class='hs-comment'>-</span><span class='hs-varid'>pure</span> <span class='hs-layout'>(</span><span class='hs-varid'>playerW</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><span class='hs-layout'>)</span>
+</pre><p>Collision events are modelled with bool signals that turn true while the ball overlaps the offending surface and approaches it at the same time. Collision response will make sure that the second condition does not hold in the next instant, so there is no need to push these through an <code>edge</code> transfer function.</p><pre><span class='hs-varop'>&gt;</span>           <span class='hs-varid'>ballCollHorz</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>getHColl</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>bricks</span><span class='hs-layout'>)</span> <span class='hs-varop'>||@</span> <span class='hs-layout'>(</span><span class='hs-varid'>check</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>ballPos</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballVel</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>               <span class='hs-keyword'>where</span> <span class='hs-varid'>check</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>bx</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>bvx</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>bx</span> <span class='hs-varop'>&lt;</span> <span class='hs-comment'>-</span><span class='hs-varid'>fieldW</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>bvx</span> <span class='hs-varop'>&lt;</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span> <span class='hs-varop'>||</span>
+<span class='hs-varop'>&gt;</span>                                                <span class='hs-layout'>(</span><span class='hs-varid'>bx</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>fieldW</span><span class='hs-comment'>-</span><span class='hs-varid'>ballW</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>bvx</span> <span class='hs-varop'>&gt;</span> <span class='hs-num'>0</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>ballCollVert</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>getVColl</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>bricks</span><span class='hs-layout'>)</span> <span class='hs-varop'>||@</span> <span class='hs-layout'>(</span><span class='hs-varid'>check</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>ballPos</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballVel</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>               <span class='hs-keyword'>where</span> <span class='hs-varid'>check</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>bx</span> <span class='hs-varid'>by</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>bvy</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>by</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>fieldH</span><span class='hs-comment'>-</span><span class='hs-varid'>ballH</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>bvy</span> <span class='hs-varop'>&gt;</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>ballCollPlayer</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>check</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>ballPos</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballVel</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>playerX</span>
+<span class='hs-varop'>&gt;</span>               <span class='hs-keyword'>where</span> <span class='hs-varid'>check</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>bx</span> <span class='hs-varid'>by</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>bvy</span><span class='hs-layout'>)</span> <span class='hs-varid'>px</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bvy</span> <span class='hs-varop'>&lt;</span> <span class='hs-num'>0</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>doRectsIntersect</span> <span class='hs-varid'>bx</span> <span class='hs-varid'>by</span> <span class='hs-varid'>ballW</span> <span class='hs-varid'>ballH</span>
+<span class='hs-varop'>&gt;</span>                                                                       <span class='hs-varid'>px</span> <span class='hs-varid'>playerY</span> <span class='hs-varid'>playerW</span> <span class='hs-varid'>playerH</span>
+<span class='hs-varop'>&gt;</span>
+</pre><p>The dynamic list of bricks along with ball-brick collision information, all of which are updated in each frame.</p><pre><span class='hs-varop'>&gt;</span>           <span class='hs-varid'>bricks</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-layout'>(</span><span class='hs-conid'>False</span><span class='hs-layout'>,</span><span class='hs-conid'>False</span><span class='hs-layout'>,</span><span class='hs-varid'>brickPos0</span><span class='hs-layout'>)</span> <span class='hs-varid'>updateBricks</span> <span class='hs-varid'>ballPos</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>getBricks</span> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-varid'>bs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bs</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>getHColl</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>c</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>getVColl</span> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-varid'>c</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>c</span>
+</pre><p>Brick updater function: fading and checking collision. We need to do this the traditional way, because Elerea does not provide constructs to deal with collections of signals in the reactive layer, unlike Yampa.</p><pre><span class='hs-varop'>&gt;</span>           <span class='hs-varid'>updateBricks</span> <span class='hs-varid'>dt</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>bx</span> <span class='hs-varid'>by</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-varid'>bricksPrev</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>collHorz</span><span class='hs-layout'>,</span><span class='hs-varid'>collVert</span><span class='hs-layout'>,</span><span class='hs-varid'>bricksNext</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>               <span class='hs-keyword'>where</span> <span class='hs-varid'>bricksNext</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>catMaybes</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>evolveBrick</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>killBrick</span> <span class='hs-varid'>bricksDel</span><span class='hs-varop'>++</span><span class='hs-varid'>bricksRem</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-layout'>(</span><span class='hs-varid'>bricksDel</span><span class='hs-layout'>,</span><span class='hs-varid'>bricksNotHit</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>partition</span> <span class='hs-varid'>classifyBrick</span> <span class='hs-varid'>bricksPrev</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>bricksRem</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>by</span> <span class='hs-varop'>&gt;</span> <span class='hs-comment'>-</span><span class='hs-varid'>fieldH</span><span class='hs-comment'>-</span><span class='hs-varid'>ballH</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>bricksNotHit</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>map</span> <span class='hs-varid'>killBrick</span> <span class='hs-varid'>bricksNotHit</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>classifyBrick</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>s</span> <span class='hs-varop'>==</span> <span class='hs-conid'>Live</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>killed</span>
+<span class='hs-varop'>&gt;</span>                         <span class='hs-keyword'>where</span> <span class='hs-varid'>killed</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>doRectsIntersect</span> <span class='hs-varid'>bx</span> <span class='hs-varid'>by</span> <span class='hs-varid'>ballW</span> <span class='hs-varid'>ballH</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>brickW</span> <span class='hs-varid'>brickH</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>evolveBrick</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-conid'>Dying</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>a</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>fade</span> <span class='hs-keyword'>then</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-conid'>Dying</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-comment'>-</span><span class='hs-varid'>fade</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                         <span class='hs-keyword'>where</span> <span class='hs-varid'>fade</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-varop'>*</span><span class='hs-varid'>brickFade</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>evolveBrick</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>b</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>killBrick</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-conid'>Live</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-conid'>Dying</span> <span class='hs-num'>1</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>killBrick</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>b</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>collHorz</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>or</span> <span class='hs-varid'>collHBricks</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>collVert</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>or</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>not</span> <span class='hs-varid'>collHBricks</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>collHBricks</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>isHorz</span> <span class='hs-varid'>bricksDel</span>
+<span class='hs-varop'>&gt;</span>                     <span class='hs-varid'>isHorz</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>xDist</span><span class='hs-varop'>/</span><span class='hs-varid'>brickW</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>yDist</span><span class='hs-varop'>/</span><span class='hs-varid'>brickH</span>
+<span class='hs-varop'>&gt;</span>                         <span class='hs-keyword'>where</span> <span class='hs-varid'>xDist</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>abs</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>+</span><span class='hs-varid'>brickW</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><span class='hs-layout'>)</span><span class='hs-comment'>-</span><span class='hs-layout'>(</span><span class='hs-varid'>bx</span><span class='hs-varop'>+</span><span class='hs-varid'>ballW</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                               <span class='hs-varid'>yDist</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>abs</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>+</span><span class='hs-varid'>brickH</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><span class='hs-layout'>)</span><span class='hs-comment'>-</span><span class='hs-layout'>(</span><span class='hs-varid'>by</span><span class='hs-varop'>+</span><span class='hs-varid'>ballH</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+</pre><p>The <code>doRectsIntersect</code> function decides whether two rectangles defined by their top left corners and dimensions overlap.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>doRectsIntersect</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varid'>sx1</span> <span class='hs-varid'>sy1</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-varid'>sx2</span> <span class='hs-varid'>sy2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>collIV</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>sx1</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>sx2</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>collIV</span> <span class='hs-varid'>y1</span> <span class='hs-varid'>sy1</span> <span class='hs-varid'>y2</span> <span class='hs-varid'>sy2</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>where</span> <span class='hs-varid'>collIV</span> <span class='hs-varid'>p1</span> <span class='hs-varid'>s1</span> <span class='hs-varid'>p2</span> <span class='hs-varid'>s2</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>p1</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>p2</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>p2</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>p1</span><span class='hs-varop'>+</span><span class='hs-varid'>s1</span><span class='hs-layout'>)</span> <span class='hs-varop'>||</span> <span class='hs-layout'>(</span><span class='hs-varid'>p2</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>p1</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>p1</span> <span class='hs-varop'>&lt;=</span> <span class='hs-varid'>p2</span><span class='hs-varop'>+</span><span class='hs-varid'>s2</span><span class='hs-layout'>)</span>
+</pre><p>The <code>renderLevel</code> function takes a snapshot of the game and turns it into an IO action that displays this snapshot on the screen. The <code>breakout</code> signal is the time-varying version of this IO action.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>renderLevel</span> <span class='hs-varid'>playerX</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>ballX</span> <span class='hs-varid'>ballY</span><span class='hs-layout'>)</span> <span class='hs-varid'>bricks</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>let</span> <span class='hs-varid'>drawRect</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>xs</span> <span class='hs-varid'>ys</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>loadIdentity</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>renderPrimitive</span> <span class='hs-conid'>Quads</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>)</span>    <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-layout'>)</span>    <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>+</span><span class='hs-varid'>xs</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-layout'>)</span>    <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>+</span><span class='hs-varid'>xs</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>+</span><span class='hs-varid'>ys</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>)</span>    <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>+</span><span class='hs-varid'>ys</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>drawEllipse</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>xs</span> <span class='hs-varid'>ys</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-keyword'>let</span> <span class='hs-varid'>xc</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span><span class='hs-varop'>+</span><span class='hs-varid'>xs</span><span class='hs-varop'>/</span><span class='hs-num'>2</span>
+<span class='hs-varop'>&gt;</span>             <span class='hs-varid'>yc</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>y</span><span class='hs-varop'>+</span><span class='hs-varid'>ys</span><span class='hs-varop'>/</span><span class='hs-num'>2</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>loadIdentity</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>renderPrimitive</span> <span class='hs-conid'>TriangleStrip</span> <span class='hs-varop'>$</span> <span class='hs-varid'>forM_</span> <span class='hs-keyglyph'>[</span><span class='hs-num'>0</span><span class='hs-keyglyph'>..</span><span class='hs-varid'>n</span><span class='hs-keyglyph'>]</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>i</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-keyword'>let</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>2</span><span class='hs-varop'>*</span><span class='hs-varid'>pi</span><span class='hs-varop'>*</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>i</span><span class='hs-varop'>/</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>n</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-varid'>xc</span><span class='hs-varop'>+</span><span class='hs-varid'>xs</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><span class='hs-varop'>*</span><span class='hs-varid'>sin</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>yc</span><span class='hs-varop'>+</span><span class='hs-varid'>ys</span><span class='hs-varop'>/</span><span class='hs-num'>2</span><span class='hs-varop'>*</span><span class='hs-varid'>cos</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-varid'>xc</span> <span class='hs-varid'>yc</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>clear</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>ColorBuffer</span><span class='hs-keyglyph'>]</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>0.2</span> <span class='hs-num'>0.2</span> <span class='hs-num'>0.2</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>drawRect</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>fieldW</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>fieldH</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fieldW</span><span class='hs-varop'>*</span><span class='hs-num'>2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fieldH</span><span class='hs-varop'>*</span><span class='hs-num'>2</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>forM_</span> <span class='hs-varid'>bricks</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-layout'>,</span><span class='hs-varid'>y</span><span class='hs-layout'>,</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>case</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
+<span class='hs-varop'>&gt;</span>       <span class='hs-conid'>Live</span>    <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>0.8</span> <span class='hs-num'>0.5</span> <span class='hs-num'>0.5</span> <span class='hs-layout'>(</span><span class='hs-num'>0.6</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>       <span class='hs-conid'>Dying</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>0.9</span> <span class='hs-num'>0.9</span> <span class='hs-num'>0.2</span> <span class='hs-varid'>a</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>drawRect</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>brickW</span> <span class='hs-varid'>brickH</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>1</span> <span class='hs-num'>1</span> <span class='hs-num'>1</span> <span class='hs-layout'>(</span><span class='hs-num'>0.6</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>drawEllipse</span> <span class='hs-varid'>ballX</span> <span class='hs-varid'>ballY</span> <span class='hs-varid'>ballW</span> <span class='hs-varid'>ballH</span> <span class='hs-num'>20</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>0.3</span> <span class='hs-num'>0.4</span> <span class='hs-num'>0.8</span> <span class='hs-layout'>(</span><span class='hs-num'>0.5</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>drawRect</span> <span class='hs-varid'>playerX</span> <span class='hs-varid'>playerY</span> <span class='hs-varid'>playerW</span> <span class='hs-varid'>playerH</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>flush</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>swapBuffers</span>
+</pre><h2 id="backend">Backend</h2><p>The <code>readInput</code> function has two responsibilities: it provides input for the <code>mousePosition</code> peripheral signal through its associated sink, and also feeds the time difference between two states into the system, deciding when to exit altogether (by returning <code>Nothing</code> instead of the current <code>dt</code> value wrapped in <code>Just</code>).</p><p>The <code>threadDelay</code> call at the beginning is just a trick to give the scheduler a breath. It will cause a wait equal to a scheduler tick, which is 20ms by default. The program can run perfectly without it, but it eats up all the free CPU to produce an unnecessarily high frame rate.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>readInput</span> <span class='hs-varid'>mousePos</span> <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>threadDelay</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>t</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>get</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>time</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>time</span> <span class='hs-varop'>$=</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-conid'>Position</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>get</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>mousePos</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>mousePos</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>k</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>getKey</span> <span class='hs-conid'>ESC</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>readIORef</span> <span class='hs-varid'>closed</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-keyword'>if</span> <span class='hs-varid'>c</span> <span class='hs-varop'>||</span> <span class='hs-varid'>k</span> <span class='hs-varop'>==</span> <span class='hs-conid'>Press</span> <span class='hs-keyword'>then</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span>
+</pre><p>The <code>initGL</code> function sets up almost nothing, which means that most functionality is turned off. Only alpha blending is enabled to provide some minimalistic eye candy.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>initGL</span> <span class='hs-varid'>width</span> <span class='hs-varid'>height</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>clearColor</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>1</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>blend</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Enabled</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>blendFunc</span> <span class='hs-varop'>$=</span> <span class='hs-layout'>(</span><span class='hs-conid'>SrcAlpha</span><span class='hs-layout'>,</span><span class='hs-conid'>OneMinusSrcAlpha</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>cullFace</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Just</span> <span class='hs-conid'>Back</span>
+</pre><p>The resize callback feeds the <code>windowSize</code> signal through its sink besides adjusting the projection matrix.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>resizeGLScene</span> <span class='hs-varid'>winSize</span> <span class='hs-varid'>size</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>Size</span> <span class='hs-varid'>w</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>winSize</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>w</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>viewport</span> <span class='hs-varop'>$=</span> <span class='hs-layout'>(</span><span class='hs-conid'>Position</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span><span class='hs-layout'>,</span><span class='hs-varid'>size</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>matrixMode</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Projection</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>loadIdentity</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>scale</span> <span class='hs-num'>1</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>w</span><span class='hs-varop'>/</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>  
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>matrixMode</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Modelview</span> <span class='hs-num'>0</span>
+</pre><h1 id="utils-module">Utils module</h1><p>This module contains some functions that might make it into the core library eventually.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span>
+</pre><p>The <code>driveNetwork</code> function simply executes the supersteps while the <code>driver</code> function keeps returning valid delta time values.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>network</span> <span class='hs-varid'>driver</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>dt</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>driver</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>case</span> <span class='hs-varid'>dt</span> <span class='hs-keyword'>of</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>Just</span> <span class='hs-varid'>dt</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>join</span> <span class='hs-varop'>$</span> <span class='hs-varid'>superstep</span> <span class='hs-varid'>network</span> <span class='hs-varid'>dt</span>
+<span class='hs-varop'>&gt;</span>                   <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>network</span> <span class='hs-varid'>driver</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
+</pre><p>The <code>edge</code> transfer function takes a bool signal and emits another bool signal that turns true only at the moment when there is a rising edge on the input. We are relying on the delay introduced by the <code>transfer</code> primitive for this to work.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>edge</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>transfer</span> <span class='hs-conid'>False</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>not</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;@</span> <span class='hs-varid'>b</span>
+</pre><p>A scalar integral function. Since it is based on <code>transfer</code>, it is delayed by one superstep, i.e.&nbsp;the value of the input signal in the n<sup>th</sup> step affects its output only in the (n+1)<sup>th</sup> step.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>integral</span> <span class='hs-varid'>v0</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-varid'>v0</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>v</span> <span class='hs-varid'>v0</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v0</span><span class='hs-varop'>+</span><span class='hs-varid'>v</span><span class='hs-varop'>*</span><span class='hs-varid'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
+</pre><p>An integral function for two-dimensional vectors defined in the <code>Vector</code> module with the same caveat.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>v0</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-varid'>v0</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>v</span> <span class='hs-varid'>v0</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v0</span><span class='hs-varop'>^+^</span><span class='hs-layout'>(</span><span class='hs-varid'>v</span><span class='hs-varop'>^*.</span><span class='hs-varid'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
+</pre><p>Logic relations lifted into signals. Useful to combine event-like signals.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>||@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>||@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>||</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>&amp;&amp;@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>&amp;&amp;@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>&amp;&amp;</span><span class='hs-layout'>)</span>
+</pre><h1 id="vector-module">Vector module</h1><p>This module contains a class for two-dimensional vectors, a strict datatype to instantiate it, and another instance for signals of the same type.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-comment'>{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>Rendering</span><span class='hs-varop'>.</span><span class='hs-conid'>OpenGL</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>data</span> <span class='hs-conid'>Vec</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>{</span> <span class='hs-varid'>getX</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>!</span><span class='hs-conid'>Float</span><span class='hs-layout'>,</span> <span class='hs-varid'>getY</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>!</span><span class='hs-conid'>Float</span> <span class='hs-layout'>}</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>^*.</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>.*^</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>`dot`</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>`cross`</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>6</span> <span class='hs-varop'>^+^</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>6</span> <span class='hs-varop'>^-^</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>class</span> <span class='hs-conid'>Vector2D</span> <span class='hs-varid'>v</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>dot</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>cross</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>instance</span> <span class='hs-conid'>Vector2D</span> <span class='hs-conid'>Vec</span> <span class='hs-conid'>Float</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>^+^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-varop'>+</span><span class='hs-varid'>x2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y1</span><span class='hs-varop'>+</span><span class='hs-varid'>y2</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>^-^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-comment'>-</span><span class='hs-varid'>x2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y1</span><span class='hs-comment'>-</span><span class='hs-varid'>y2</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varop'>^*.</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>t</span> <span class='hs-varop'>.*^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>`dot`</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x1</span><span class='hs-varop'>*</span><span class='hs-varid'>y1</span><span class='hs-varop'>+</span><span class='hs-varid'>x2</span><span class='hs-varop'>*</span><span class='hs-varid'>y2</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>`cross`</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x1</span><span class='hs-varop'>*</span><span class='hs-varid'>y2</span><span class='hs-comment'>-</span><span class='hs-varid'>x2</span><span class='hs-varop'>*</span><span class='hs-varid'>y1</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>instance</span> <span class='hs-conid'>Vector2D</span> <span class='hs-layout'>(</span><span class='hs-conid'>Signal</span> <span class='hs-conid'>Vec</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Signal</span> <span class='hs-conid'>Float</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pure</span> <span class='hs-varid'>vnull</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>dot</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-varid'>dot</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>cross</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-varid'>cross</span>
+</pre>
+</body></html>
diff --git a/doc/Breakout.png b/doc/Breakout.png
new file mode 100644
Binary files /dev/null and b/doc/Breakout.png differ
diff --git a/doc/Chase.html b/doc/Chase.html
new file mode 100644
--- /dev/null
+++ b/doc/Chase.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title></title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="generator" content="pandoc" /><link rel="stylesheet" href="hscolour.css" type="text/css" media="all" />
+</head><body><h1 id="elerea-chase-example">Elerea Chase example</h1><p>This is a minimal example to show how to define signals that can be mutually recursive and can optionally depend on user input too. The grey square accelerates towards the red square at a rate proportional to their relative position, and it can be given a momentary impulse with the left mouse button.</p><p>For a slightly more complex example check out <code>Breakout.lhs</code>.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Main</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>IORef</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>UI</span><span class='hs-varop'>.</span><span class='hs-conid'>GLFW</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>GLFW</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>Rendering</span><span class='hs-varop'>.</span><span class='hs-conid'>OpenGL</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span>
+</pre><p>The <code>main</code> function contains the whole reactive logic. Note that <code>driveNetwork</code> is just a wrapper around the <code>superstep</code> function of the core library, and you can see its source below in the <code>Utils</code> module.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>main</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>initialize</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>openWindow</span> <span class='hs-layout'>(</span><span class='hs-conid'>Size</span> <span class='hs-num'>640</span> <span class='hs-num'>480</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>DisplayRGBBits</span> <span class='hs-num'>8</span> <span class='hs-num'>8</span> <span class='hs-num'>8</span><span class='hs-layout'>,</span> <span class='hs-conid'>DisplayAlphaBits</span> <span class='hs-num'>8</span><span class='hs-layout'>,</span> <span class='hs-conid'>DisplayDepthBits</span> <span class='hs-num'>24</span><span class='hs-keyglyph'>]</span> <span class='hs-conid'>Window</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>windowTitle</span> <span class='hs-varop'>$=</span> <span class='hs-str'>"Elerea Chase"</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-layout'>(</span><span class='hs-varid'>windowSize</span><span class='hs-layout'>,</span><span class='hs-varid'>windowSizeSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-varid'>vnull</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-layout'>(</span><span class='hs-varid'>mousePosition</span><span class='hs-layout'>,</span><span class='hs-varid'>mousePositionSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-varid'>vnull</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-layout'>(</span><span class='hs-varid'>mousePress</span><span class='hs-layout'>,</span><span class='hs-varid'>mousePressSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-conid'>False</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>newIORef</span> <span class='hs-conid'>False</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>windowSizeCallback</span> <span class='hs-varop'>$=</span> <span class='hs-varid'>resizeGLScene</span> <span class='hs-varid'>windowSizeSink</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>windowCloseCallback</span> <span class='hs-varop'>$=</span> <span class='hs-varid'>writeIORef</span> <span class='hs-varid'>closed</span> <span class='hs-conid'>True</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>initGL</span> <span class='hs-num'>640</span> <span class='hs-num'>480</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>let</span> <span class='hs-varid'>ballPos</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>vnull</span> <span class='hs-varid'>ballVel</span>
+<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>ballVel</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>latcher</span> <span class='hs-layout'>(</span><span class='hs-varid'>integralVec</span> <span class='hs-varid'>vnull</span> <span class='hs-varid'>ballAcc</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                         <span class='hs-layout'>(</span><span class='hs-varid'>edge</span> <span class='hs-varid'>mousePress</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                         <span class='hs-layout'>(</span><span class='hs-varid'>integralVec</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>ballVel</span><span class='hs-varop'>^+^</span><span class='hs-varid'>ballPos</span><span class='hs-varop'>^-^</span><span class='hs-varid'>mousePosition</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>pure</span> <span class='hs-varid'>ballAcc</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>ballAcc</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>mousePosition</span><span class='hs-varop'>^-^</span><span class='hs-varid'>ballPos</span><span class='hs-layout'>)</span><span class='hs-varop'>^*.</span><span class='hs-num'>0.3</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>driveNetwork</span> <span class='hs-layout'>(</span><span class='hs-varid'>render</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>windowSize</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>mousePosition</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>ballPos</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>                <span class='hs-layout'>(</span><span class='hs-varid'>readInput</span> <span class='hs-varid'>mousePositionSink</span> <span class='hs-varid'>mousePressSink</span> <span class='hs-varid'>closed</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>closeWindow</span>
+</pre><p>The <code>render</code> function takes a snapshot of the system (window size and the positions of the squares) and turns it into OpenGL calls. The signal executed by the <code>driveNetwork</code> function is the time-varying version of the IO action returned here.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>render</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>w</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>cx</span> <span class='hs-varid'>cy</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>ox</span> <span class='hs-varid'>oy</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>let</span> <span class='hs-varid'>drawSquare</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>loadIdentity</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>translate</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vector3</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>/</span><span class='hs-varid'>w</span><span class='hs-varop'>*</span><span class='hs-num'>2</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>h</span><span class='hs-varop'>/</span><span class='hs-varid'>w</span><span class='hs-comment'>-</span><span class='hs-varid'>y</span><span class='hs-varop'>/</span><span class='hs-varid'>w</span><span class='hs-varop'>*</span><span class='hs-num'>2</span><span class='hs-layout'>)</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>renderPrimitive</span> <span class='hs-conid'>Quads</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>clear</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>ColorBuffer</span><span class='hs-keyglyph'>]</span>
+<span class='hs-varop'>&gt;</span>  
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>1</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-num'>0.5</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>drawSquare</span> <span class='hs-varid'>cx</span> <span class='hs-varid'>cy</span> <span class='hs-num'>0.05</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>1</span> <span class='hs-num'>1</span> <span class='hs-num'>1</span> <span class='hs-layout'>(</span><span class='hs-num'>0.6</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>drawSquare</span> <span class='hs-varid'>ox</span> <span class='hs-varid'>oy</span> <span class='hs-num'>0.03</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>flush</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>swapBuffers</span>
+</pre><p>The <code>readInput</code> function provides the driver layer. It feeds the peripheral-bound signals and also decides when to stop execution by returning <code>Nothing</code> instead of the time elapsed since its last call.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>readInput</span> <span class='hs-varid'>mousePos</span> <span class='hs-varid'>mouseBut</span> <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>t</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>get</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>time</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>time</span> <span class='hs-varop'>$=</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-conid'>Position</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>get</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>mousePos</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>mousePos</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>getMouseButton</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-conid'>ButtonLeft</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>mouseBut</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-varop'>==</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-conid'>Press</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>k</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>getKey</span> <span class='hs-conid'>ESC</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>readIORef</span> <span class='hs-varid'>closed</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-keyword'>if</span> <span class='hs-varid'>c</span> <span class='hs-varop'>||</span> <span class='hs-varid'>k</span> <span class='hs-varop'>==</span> <span class='hs-conid'>Press</span> <span class='hs-keyword'>then</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span>
+</pre><p>OpenGL is initialised with practically everything turned off. Only alpha blending is needed to be able to use translucent colours.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>initGL</span> <span class='hs-varid'>width</span> <span class='hs-varid'>height</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>clearColor</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>1</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>blend</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Enabled</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>blendFunc</span> <span class='hs-varop'>$=</span> <span class='hs-layout'>(</span><span class='hs-conid'>SrcAlpha</span><span class='hs-layout'>,</span><span class='hs-conid'>OneMinusSrcAlpha</span><span class='hs-layout'>)</span>
+</pre><p>The window size callback takes care of the <code>windowSize</code> signal and the projection matrix.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>resizeGLScene</span> <span class='hs-varid'>winSize</span> <span class='hs-varid'>size</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>Size</span> <span class='hs-varid'>w</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>winSize</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>w</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>viewport</span> <span class='hs-varop'>$=</span> <span class='hs-layout'>(</span><span class='hs-conid'>Position</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span><span class='hs-layout'>,</span><span class='hs-varid'>size</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>matrixMode</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Projection</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>loadIdentity</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>scale</span> <span class='hs-num'>1</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>w</span><span class='hs-varop'>/</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>  
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>matrixMode</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Modelview</span> <span class='hs-num'>0</span>
+</pre><h1 id="utils-module">Utils module</h1><p>This module contains some functions that might make it into the core library eventually.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span>
+</pre><p>The <code>driveNetwork</code> function simply executes the supersteps while the <code>driver</code> function keeps returning valid delta time values.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>network</span> <span class='hs-varid'>driver</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>dt</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>driver</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>case</span> <span class='hs-varid'>dt</span> <span class='hs-keyword'>of</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>Just</span> <span class='hs-varid'>dt</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>join</span> <span class='hs-varop'>$</span> <span class='hs-varid'>superstep</span> <span class='hs-varid'>network</span> <span class='hs-varid'>dt</span>
+<span class='hs-varop'>&gt;</span>                   <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>network</span> <span class='hs-varid'>driver</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
+</pre><p>The <code>edge</code> transfer function takes a bool signal and emits another bool signal that turns true only at the moment when there is a rising edge on the input. We are relying on the delay introduced by the <code>transfer</code> primitive for this to work.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>edge</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>transfer</span> <span class='hs-conid'>False</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>not</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;@</span> <span class='hs-varid'>b</span>
+</pre><p>A scalar integral function. Since it is based on <code>transfer</code>, it is delayed by one superstep, i.e.&nbsp;the value of the input signal in the n<sup>th</sup> step affects its output only in the (n+1)<sup>th</sup> step.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>integral</span> <span class='hs-varid'>v0</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-varid'>v0</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>v</span> <span class='hs-varid'>v0</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v0</span><span class='hs-varop'>+</span><span class='hs-varid'>v</span><span class='hs-varop'>*</span><span class='hs-varid'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
+</pre><p>An integral function for two-dimensional vectors defined in the <code>Vector</code> module with the same caveat.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>v0</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-varid'>v0</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>v</span> <span class='hs-varid'>v0</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v0</span><span class='hs-varop'>^+^</span><span class='hs-layout'>(</span><span class='hs-varid'>v</span><span class='hs-varop'>^*.</span><span class='hs-varid'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
+</pre><p>Logic relations lifted into signals. Useful to combine event-like signals.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>||@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>||@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>||</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span> 
+<span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>&amp;&amp;@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Signal</span> <span class='hs-conid'>Bool</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-layout'>(</span><span class='hs-varop'>&amp;&amp;@</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>&amp;&amp;</span><span class='hs-layout'>)</span>
+</pre><h1 id="vector-module">Vector module</h1><p>This module contains a class for two-dimensional vectors, a strict datatype to instantiate it, and another instance for signals of the same type.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-comment'>{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>Rendering</span><span class='hs-varop'>.</span><span class='hs-conid'>OpenGL</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>data</span> <span class='hs-conid'>Vec</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>{</span> <span class='hs-varid'>getX</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>!</span><span class='hs-conid'>Float</span><span class='hs-layout'>,</span> <span class='hs-varid'>getY</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>!</span><span class='hs-conid'>Float</span> <span class='hs-layout'>}</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>^*.</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>.*^</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>`dot`</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>`cross`</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>6</span> <span class='hs-varop'>^+^</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>6</span> <span class='hs-varop'>^-^</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>class</span> <span class='hs-conid'>Vector2D</span> <span class='hs-varid'>v</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>dot</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>cross</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>instance</span> <span class='hs-conid'>Vector2D</span> <span class='hs-conid'>Vec</span> <span class='hs-conid'>Float</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>^+^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-varop'>+</span><span class='hs-varid'>x2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y1</span><span class='hs-varop'>+</span><span class='hs-varid'>y2</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>^-^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-comment'>-</span><span class='hs-varid'>x2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y1</span><span class='hs-comment'>-</span><span class='hs-varid'>y2</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varop'>^*.</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>t</span> <span class='hs-varop'>.*^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>`dot`</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x1</span><span class='hs-varop'>*</span><span class='hs-varid'>y1</span><span class='hs-varop'>+</span><span class='hs-varid'>x2</span><span class='hs-varop'>*</span><span class='hs-varid'>y2</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>`cross`</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x1</span><span class='hs-varop'>*</span><span class='hs-varid'>y2</span><span class='hs-comment'>-</span><span class='hs-varid'>x2</span><span class='hs-varop'>*</span><span class='hs-varid'>y1</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>instance</span> <span class='hs-conid'>Vector2D</span> <span class='hs-layout'>(</span><span class='hs-conid'>Signal</span> <span class='hs-conid'>Vec</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Signal</span> <span class='hs-conid'>Float</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pure</span> <span class='hs-varid'>vnull</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>dot</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-varid'>dot</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>cross</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-varid'>cross</span>
+</pre>
+</body></html>
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,10 @@
+.SUFFIXES: .lhs .html
+
+PANDOC := pandoc --no-wrap -s -S
+HSCOLOUR := HsColour -lit
+UNIOPS := sed "s/>&lt;-</>\&larr;</g" | sed "s/>-&gt;</>\&rarr;</g"
+
+all: ../src/Breakout.html ../src/Chase.html
+
+.lhs.html:
+	cat $< $(dir $<)Common/*lhs | $(HSCOLOUR) -css | $(PANDOC) -t html -c hscolour.css | $(UNIOPS) > $(notdir $@)
diff --git a/doc/hscolour.css b/doc/hscolour.css
new file mode 100644
--- /dev/null
+++ b/doc/hscolour.css
@@ -0,0 +1,11 @@
+.hs-keyword { color: #000; font-weight: bold }
+
+.hs-keyglyph { color: #033 }
+
+.hs-varid { color: #00c }
+
+.hs-varop { color: #990 }
+
+.hs-conid { color: #080 }
+
+.hs-comment { color: #a00 }
diff --git a/elerea-examples.cabal b/elerea-examples.cabal
new file mode 100644
--- /dev/null
+++ b/elerea-examples.cabal
@@ -0,0 +1,49 @@
+Name:                elerea-examples
+Version:             0.1.0
+Cabal-Version:       >= 1.2
+Synopsis:            Example applications for Elerea
+Category:            reactivity, FRP
+Description:
+
+  Example applications for Elerea. They are factored out into their
+  own package so as to avoid unnecessary dependencies in the
+  library. Check out the @doc@ directory for the colourful literate
+  sources.
+  .
+  The programs included are the following:
+  .
+  * chase: a minimal example that demonstrates reactivity and mutually
+    recursive signals
+  .
+  * breakout: a not too fancy breakout clone
+
+Author:              Patai Gergely
+Maintainer:          Patai Gergely (patai@iit.bme.hu)
+Copyright:           (c) 2009, Patai Gergely
+License:             BSD3
+License-File:        LICENSE
+Stability:           experimental
+Build-Type:          Simple
+Extra-Source-Files:
+  src/Common/Vector.lhs
+  src/Common/Utils.lhs
+
+  doc/Breakout.html
+  doc/Breakout.png
+  doc/Chase.html
+  doc/hscolour.css
+  doc/Makefile
+
+Executable elerea-breakout
+  Executable:        elerea-breakout
+  HS-Source-Dirs:    src
+  Main-IS:           Breakout.lhs
+  Build-Depends:     base, elerea, OpenGL, GLFW
+  GHC-Options:       -O2
+
+Executable elerea-chase
+  Executable:        elerea-chase
+  HS-Source-Dirs:    src
+  Main-IS:           Chase.lhs
+  Build-Depends:     base, elerea, OpenGL, GLFW
+  GHC-Options:       -O2
diff --git a/src/Breakout.lhs b/src/Breakout.lhs
new file mode 100644
--- /dev/null
+++ b/src/Breakout.lhs
@@ -0,0 +1,316 @@
+Elerea Breakout example
+=======================
+
+Breakout is one of the simplest test applications that brings up some
+problems with non-trivial solutions.  In particular, there is a
+circular dependency between the position and the velocity of the ball.
+The position is the integral of the velocity, while velocity can have
+instantaneous changes due to collisions, which is a function of the
+position of the ball and the current state of the field.  The field is
+dynamic, and it also forms a mutual dependency loop with the ball
+position.  On top of these, part of the field (at least if we regard
+the paddle as part of it) depends on user input, and its effects start
+propagating in the game state as soon as the ball reaches the level of
+the paddle.
+
+Elerea lets us express all these circular dependencies in a natural
+way, by simply referring to the respective signals by their names.
+User input is also seen as a signal from inside the reactive part,
+while the imperative framework is given a sink fuction to update it as
+needed.  Type safety is ensured all the way.
+
+<img src="Breakout.png" alt="Elerea Breakout in action" />
+
+Below follows the full source of the example.
+
+> module Main where
+> 
+> import Control.Applicative
+> import Control.Concurrent
+> import Control.Monad
+> import Data.IORef
+> import Data.List
+> import Data.Maybe
+> import FRP.Elerea
+> import Graphics.UI.GLFW as GLFW
+> import Graphics.Rendering.OpenGL
+> 
+> import Common.Utils
+> import Common.Vector
+
+Global constants
+----------------
+
+The dimensions of the ball, which behaves as a rectangle in collision
+detection, but is drawn as an ellipse.
+
+> ballW = 0.04
+> ballH = 0.04
+
+The initial position and velocity of the ball.
+
+> ballPos0 = V 0 (-0.4)
+> ballVel0 = V (-0.4) (0.35)
+
+The dimensions and vertical position of the player.
+
+> playerW = 0.2
+> playerH = 0.03
+> playerY = -fieldH+0.01
+
+The dimensions of the field.
+
+> fieldW = 0.8
+> fieldH = 0.5
+
+The dimensions of each brick.
+
+> brickW = 0.05
+> brickH = 0.03
+
+The starting positions of the bricks.  The third element of the
+triples is the state of the brick.  A brick can either be alive or
+dying.  Dying bricks also keep track of their fadeout level.
+
+> data BrickState = Live | Dying Double deriving Eq
+>
+> brickPos0 = distributeBricks (-0.7) (-0.1) (0.7) (0.4) 18 10
+>     where distributeBricks xmin ymin xmax ymax xn yn = [(xmin+xstep*x,ymin+ystep*y,Live) |
+>                                                         x <- [0..xn-1], y <- [0..yn-1]]
+>               where xstep = (xmax-xmin-xn*brickW)/(xn-1)+brickW
+>                     ystep = (ymax-ymin-yn*brickH)/(yn-1)+brickH
+
+The rate at which a brick fades out.  The reciprocal of this value
+gives the fadeout time in seconds.
+
+> brickFade = 0.5
+
+Game logic
+----------
+
+The entry point performs some lightweight initialisation, and defines
+the two user-driven signals: window size and mouse position.  The
+`external` function creates the signal and the corresponding sink at
+the same time.
+
+When all is done `driveNetwork` is invoked.  It is not a library
+function, but part of the tiny `Utils` module .
+
+> main = do
+>   -- Creating a window without a depth buffer
+>   initialize
+>   openWindow (Size 640 480) [DisplayRGBBits 8 8 8, DisplayAlphaBits 8] Window
+>   windowTitle $= "Elerea Breakout"
+> 
+>   -- External signals available for the game logic
+>   (windowSize,windowSizeSink) <- external vnull
+>   (mousePosition,mousePositionSink) <- external vnull
+> 
+>   -- Wrapping up the init phase
+>   closed <- newIORef False
+>   windowSizeCallback $= resizeGLScene windowSizeSink
+>   windowCloseCallback $= writeIORef closed True
+>   initGL 640 480
+> 
+>   -- All we need to get going is an IO-valued signal and an IO
+>   -- function to update the external signals
+>   driveNetwork (breakout mousePosition windowSize)
+>                (readInput mousePositionSink closed)
+> 
+>   -- The inevitable sad ending
+>   closeWindow
+
+The `breakout` function creates a reactive signal that carries the
+rendering actions to be performed at each instant.  The principal
+signals forming the game logic are the following:
+
+* `playerX`: the position of the player, a direct function of the
+   mouse position;
+* `ballPos`: the position of the ball given as an integral of its
+   velocity, `ballVel`;
+* `bricks`: the collection of live and dying bricks along with
+   collision information.
+
+The position and velocity of the ball form a circular dependency, as
+velocity is changed whenever a collision is detected, which is a
+function of the position.
+
+The signal carrying the collection of the bricks is obtained by
+applying a stateful transformation (a transfer function) on the ball
+position.  The state contains the bricks still relevant to the game as
+well as collision information.  Although the latter is technically
+redundant, it is still worth including here, since it has to be
+calculated while advancing the state of the bricks, and it is needed
+elsewhere too.
+
+> breakout mousePos windowSize = renderLevel <$> playerX <*> ballPos <*> (getBricks <$> bricks)
+>     where 
+
+User-driven player position:
+
+>           playerX = adjustPlayerPos <$> mousePos <*> windowSize
+>           adjustPlayerPos (V x _) (V w _) = min (fieldW-playerW) $ max (-fieldW) $ 2*x/w-1-playerW/2
+
+Ball state: position and velocity.  Note the use of the latcher: we
+wrap a signal created by `adjustVel` in a `pure`, hence adding another
+signal layer around it.
+
+>           ballPos = integralVec (ballPos0) ballVel
+>           ballVel = latcher (pure ballVel0)
+>                             (ballCollHorz ||@ ballCollVert ||@ ballCollPlayer)
+>                             (pure <$> (adjustVel <$> ballCollHorz <*> ballCollVert <*> ballCollPlayer <*>
+>                                        ballVel <*> ballNewVelX))
+
+The `adjustVel` function calculates a candidate velocity for the next
+frame given collision information and the current velocity.  Even
+though it would return the current speed if there are no collisions,
+we rather not evaluate it at all thanks to the latcher.  In the end,
+velocity is not recalculated in each frame.
+
+>           adjustVel ch cv cp (V bvx bvy) bvx' = V x y
+>               where x = (if ch then -1 else 1)*(if cp then bvx'*4 else bvx)
+>                     y = if cv || cp then -bvy else bvy
+>           ballNewVelX = (getX <$> ballPos)-playerX-pure (playerW/2)
+
+Collision events are modelled with bool signals that turn true while
+the ball overlaps the offending surface and approaches it at the same
+time.  Collision response will make sure that the second condition
+does not hold in the next instant, so there is no need to push these
+through an `edge` transfer function.
+
+>           ballCollHorz = (getHColl <$> bricks) ||@ (check <$> ballPos <*> ballVel)
+>               where check (V bx _) (V bvx _) = (bx < -fieldW && bvx < 0) ||
+>                                                (bx > fieldW-ballW && bvx > 0)
+>           ballCollVert = (getVColl <$> bricks) ||@ (check <$> ballPos <*> ballVel)
+>               where check (V bx by) (V _ bvy) = by > fieldH-ballH && bvy > 0
+>           ballCollPlayer = check <$> ballPos <*> ballVel <*> playerX
+>               where check (V bx by) (V _ bvy) px = bvy < 0 && doRectsIntersect bx by ballW ballH
+>                                                                       px playerY playerW playerH
+>
+
+The dynamic list of bricks along with ball-brick collision
+information, all of which are updated in each frame.
+
+>           bricks = transfer (False,False,brickPos0) updateBricks ballPos
+>           getBricks (_,_,bs) = bs
+>           getHColl (c,_,_) = c
+>           getVColl (_,c,_) = c
+
+Brick updater function: fading and checking collision.  We need to do
+this the traditional way, because Elerea does not provide constructs
+to deal with collections of signals in the reactive layer, unlike
+Yampa.
+
+>           updateBricks dt (V bx by) (_,_,bricksPrev) = (collHorz,collVert,bricksNext)
+>               where bricksNext = catMaybes (map evolveBrick (map killBrick bricksDel++bricksRem))
+>                     (bricksDel,bricksNotHit) = partition classifyBrick bricksPrev
+>                     bricksRem = if by > -fieldH-ballH then bricksNotHit else map killBrick bricksNotHit
+>                     classifyBrick (x,y,s) = s == Live && killed
+>                         where killed = doRectsIntersect bx by ballW ballH x y brickW brickH
+>                     evolveBrick (x,y,Dying a) = if a < fade then Nothing else Just (x,y,Dying (a-fade))
+>                         where fade = realToFrac dt*brickFade
+>                     evolveBrick b = Just b
+>                     killBrick (x,y,Live) = (x,y,Dying 1)
+>                     killBrick b = b
+>                     collHorz = or collHBricks
+>                     collVert = or (map not collHBricks)
+>                     collHBricks = map isHorz bricksDel
+>                     isHorz (x,y,_) = xDist/brickW > yDist/brickH
+>                         where xDist = abs ((x+brickW/2)-(bx+ballW/2))
+>                               yDist = abs ((y+brickH/2)-(by+ballH/2))
+
+The `doRectsIntersect` function decides whether two rectangles defined
+by their top left corners and dimensions overlap.
+
+> doRectsIntersect x1 y1 sx1 sy1 x2 y2 sx2 sy2 = collIV x1 sx1 x2 sx2 && collIV y1 sy1 y2 sy2
+>     where collIV p1 s1 p2 s2 = (p1 <= p2 && p2 <= p1+s1) || (p2 <= p1 && p1 <= p2+s2)
+
+The `renderLevel` function takes a snapshot of the game and turns it
+into an IO action that displays this snapshot on the screen.  The
+`breakout` signal is the time-varying version of this IO action.
+
+> renderLevel playerX (V ballX ballY) bricks = do
+>   let drawRect x y xs ys = do
+>         loadIdentity
+>         renderPrimitive Quads $ do
+>           vertex $ Vertex3 (x)    (y)    (0 :: GLfloat)
+>           vertex $ Vertex3 (x+xs) (y)    (0 :: GLfloat)
+>           vertex $ Vertex3 (x+xs) (y+ys) (0 :: GLfloat)
+>           vertex $ Vertex3 (x)    (y+ys) (0 :: GLfloat)
+>       drawEllipse x y xs ys n = do
+>         let xc = x+xs/2
+>             yc = y+ys/2
+>         loadIdentity
+>         renderPrimitive TriangleStrip $ forM_ [0..n] $ \i -> do
+>           let a = 2*pi*fromIntegral i/fromIntegral n
+>           vertex $ Vertex3 (xc+xs/2*sin a) (yc+ys/2*cos a) (0 :: GLfloat)
+>           vertex $ Vertex3 xc yc (0 :: GLfloat)
+> 
+>   clear [ColorBuffer]
+>
+>   color $ Color4 0.2 0.2 0.2 (1 :: GLfloat)
+>   drawRect (-fieldW) (-fieldH) (fieldW*2) (fieldH*2)
+>
+>   forM_ bricks $ \(x,y,s) -> do
+>     case s of
+>       Live    -> color $ Color4 0.8 0.5 0.5 (0.6 :: GLfloat)
+>       Dying a -> color $ Color4 0.9 0.9 0.2 a
+>     drawRect x y brickW brickH
+>
+>   color $ Color4 1 1 1 (0.6 :: GLfloat)
+>   drawEllipse ballX ballY ballW ballH 20
+> 
+>   color $ Color4 0.3 0.4 0.8 (0.5 :: GLfloat)
+>   drawRect playerX playerY playerW playerH
+>
+>   flush
+>   swapBuffers
+
+Backend
+-------
+
+The `readInput` function has two responsibilities: it provides input
+for the `mousePosition` peripheral signal through its associated sink,
+and also feeds the time difference between two states into the system,
+deciding when to exit altogether (by returning `Nothing` instead of
+the current `dt` value wrapped in `Just`).
+
+The `threadDelay` call at the beginning is just a trick to give the
+scheduler a breath.  It will cause a wait equal to a scheduler tick,
+which is 20ms by default.  The program can run perfectly without it,
+but it eats up all the free CPU to produce an unnecessarily high frame
+rate.
+
+> readInput mousePos closed = do
+>   threadDelay 0
+>   t <- get GLFW.time
+>   GLFW.time $= 0
+>   Position x y <- get GLFW.mousePos
+>   mousePos (V (fromIntegral x) (fromIntegral y))
+>   k <- getKey ESC
+>   c <- readIORef closed
+>   return (if c || k == Press then Nothing else Just t)
+
+The `initGL` function sets up almost nothing, which means that most
+functionality is turned off.  Only alpha blending is enabled to
+provide some minimalistic eye candy.
+
+> initGL width height = do
+>   clearColor $= Color4 0 0 0 1
+>   blend $= Enabled
+>   blendFunc $= (SrcAlpha,OneMinusSrcAlpha)
+>   cullFace $= Just Back
+
+The resize callback feeds the `windowSize` signal through its sink
+besides adjusting the projection matrix.
+
+> resizeGLScene winSize size@(Size w h) = do
+>   winSize (V (fromIntegral w) (fromIntegral h))
+> 
+>   viewport $= (Position 0 0,size)
+> 
+>   matrixMode $= Projection
+>   loadIdentity
+>   scale 1 (fromIntegral w/fromIntegral h) (1 :: GLfloat)
+> 	
+>   matrixMode $= Modelview 0
diff --git a/src/Chase.lhs b/src/Chase.lhs
new file mode 100644
--- /dev/null
+++ b/src/Chase.lhs
@@ -0,0 +1,113 @@
+Elerea Chase example
+====================
+
+This is a minimal example to show how to define signals that can be
+mutually recursive and can optionally depend on user input too.  The
+grey square accelerates towards the red square at a rate proportional
+to their relative position, and it can be given a momentary impulse
+with the left mouse button.
+
+For a slightly more complex example check out `Breakout.lhs`.
+
+> module Main where
+> 
+> import Control.Applicative
+> import Data.IORef
+> import FRP.Elerea
+> import Graphics.UI.GLFW as GLFW
+> import Graphics.Rendering.OpenGL
+> 
+> import Common.Utils
+> import Common.Vector
+
+The `main` function contains the whole reactive logic.  Note that
+`driveNetwork` is just a wrapper around the `superstep` function of
+the core library, and you can see its source below in the `Utils`
+module.
+
+> main = do
+>   initialize
+>   openWindow (Size 640 480) [DisplayRGBBits 8 8 8, DisplayAlphaBits 8, DisplayDepthBits 24] Window
+>   windowTitle $= "Elerea Chase"
+> 
+>   (windowSize,windowSizeSink) <- external vnull
+>   (mousePosition,mousePositionSink) <- external vnull
+>   (mousePress,mousePressSink) <- external False
+> 
+>   closed <- newIORef False
+>   windowSizeCallback $= resizeGLScene windowSizeSink
+>   windowCloseCallback $= writeIORef closed True
+>   initGL 640 480
+> 
+>   let ballPos = integralVec vnull ballVel
+>       ballVel = latcher (integralVec vnull ballAcc)
+>                         (edge mousePress)
+>                         (integralVec <$> ballVel^+^ballPos^-^mousePosition <*> pure ballAcc)
+>       ballAcc = (mousePosition^-^ballPos)^*.0.3
+>
+>   driveNetwork (render <$> windowSize <*> mousePosition <*> ballPos)
+>                (readInput mousePositionSink mousePressSink closed)
+> 
+>   closeWindow
+
+The `render` function takes a snapshot of the system (window size and
+the positions of the squares) and turns it into OpenGL calls.  The
+signal executed by the `driveNetwork` function is the time-varying
+version of the IO action returned here.
+
+> render (V w h) (V cx cy) (V ox oy) = do
+>   let drawSquare x y s = do
+>         loadIdentity
+>         translate $ Vector3 (x/w*2-1) (h/w-y/w*2) 0
+>         renderPrimitive Quads $ do
+>           vertex $ Vertex3 (-s) (-s) (0 :: GLfloat)
+>           vertex $ Vertex3 ( s) (-s) (0 :: GLfloat)
+>           vertex $ Vertex3 ( s) ( s) (0 :: GLfloat)
+>           vertex $ Vertex3 (-s) ( s) (0 :: GLfloat)
+> 
+>   clear [ColorBuffer]
+>  
+>   color $ Color4 1 0 0 (0.5 :: GLfloat)
+>   drawSquare cx cy 0.05
+>   color $ Color4 1 1 1 (0.6 :: GLfloat)
+>   drawSquare ox oy 0.03
+> 
+>   flush
+>   swapBuffers
+
+The `readInput` function provides the driver layer.  It feeds the
+peripheral-bound signals and also decides when to stop execution by
+returning `Nothing` instead of the time elapsed since its last call.
+
+> readInput mousePos mouseBut closed = do
+>   t <- get GLFW.time
+>   GLFW.time $= 0
+>   Position x y <- get GLFW.mousePos
+>   mousePos (V (fromIntegral x) (fromIntegral y))
+>   b <- GLFW.getMouseButton GLFW.ButtonLeft
+>   mouseBut (b == GLFW.Press)
+>   k <- getKey ESC
+>   c <- readIORef closed
+>   return (if c || k == Press then Nothing else Just t)
+
+OpenGL is initialised with practically everything turned off.  Only
+alpha blending is needed to be able to use translucent colours.
+
+> initGL width height = do
+>   clearColor $= Color4 0 0 0 1
+>   blend $= Enabled
+>   blendFunc $= (SrcAlpha,OneMinusSrcAlpha)
+
+The window size callback takes care of the `windowSize` signal and the
+projection matrix.
+
+> resizeGLScene winSize size@(Size w h) = do
+>   winSize (V (fromIntegral w) (fromIntegral h))
+> 
+>   viewport $= (Position 0 0,size)
+> 
+>   matrixMode $= Projection
+>   loadIdentity
+>   scale 1 (fromIntegral w/fromIntegral h) (1 :: GLfloat)
+> 	
+>   matrixMode $= Modelview 0
diff --git a/src/Common/Utils.lhs b/src/Common/Utils.lhs
new file mode 100644
--- /dev/null
+++ b/src/Common/Utils.lhs
@@ -0,0 +1,50 @@
+Utils module
+============
+
+This module contains some functions that might make it into the core library eventually.
+
+> module Common.Utils where
+>
+> import Control.Applicative
+> import Control.Monad
+> import FRP.Elerea
+>
+> import Common.Vector
+
+The `driveNetwork` function simply executes the supersteps while the
+`driver` function keeps returning valid delta time values.
+
+> driveNetwork network driver = do
+>   dt <- driver
+>   case dt of
+>     Just dt -> do join $ superstep network dt
+>                   driveNetwork network driver
+>     Nothing -> return ()
+
+The `edge` transfer function takes a bool signal and emits another
+bool signal that turns true only at the moment when there is a rising
+edge on the input.  We are relying on the delay introduced by the
+`transfer` primitive for this to work.
+
+> edge b = (transfer False (\dt b _ -> not b) b) &&@ b
+
+A scalar integral function.  Since it is based on `transfer`, it is
+delayed by one superstep, i.e. the value of the input signal in the
+n<sup>th</sup> step affects its output only in the (n+1)<sup>th</sup>
+step.
+
+> integral v0 s = transfer v0 (\dt v v0 -> v0+v*realToFrac dt) s
+
+An integral function for two-dimensional vectors defined in the
+`Vector` module with the same caveat.
+
+> integralVec v0 s = transfer v0 (\dt v v0 -> v0^+^(v^*.realToFrac dt)) s
+
+Logic relations lifted into signals.  Useful to combine event-like
+signals.
+
+> (||@) :: Signal Bool -> Signal Bool -> Signal Bool
+> (||@) = liftA2 (||)
+> 
+> (&&@) :: Signal Bool -> Signal Bool -> Signal Bool
+> (&&@) = liftA2 (&&)
diff --git a/src/Common/Vector.lhs b/src/Common/Vector.lhs
new file mode 100644
--- /dev/null
+++ b/src/Common/Vector.lhs
@@ -0,0 +1,50 @@
+Vector module
+=============
+
+This module contains a class for two-dimensional vectors, a strict
+datatype to instantiate it, and another instance for signals of the
+same type.
+
+> {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
+>
+> module Common.Vector where
+>
+> import Control.Applicative
+> import FRP.Elerea
+> import Graphics.Rendering.OpenGL
+>
+> data Vec = V { getX :: !Float, getY :: !Float }
+>
+> infixl 7 ^*.
+> infixl 7 .*^
+> infixl 7 `dot`
+> infixl 7 `cross`
+> infixl 6 ^+^
+> infixl 6 ^-^
+>
+> class Vector2D v c | v -> c where
+>     (^+^) :: v -> v -> v
+>     (^-^) :: v -> v -> v
+>     (^*.) :: v -> c -> v
+>     (.*^) :: c -> v -> v
+>     vnull :: v
+>     dot :: v -> v -> c
+>     cross :: v -> v -> c
+>
+> instance Vector2D Vec Float where
+>     V x1 y1 ^+^ V x2 y2 = V (x1+x2) (y1+y2)
+>     V x1 y1 ^-^ V x2 y2 = V (x1-x2) (y1-y2)
+>     V x y ^*. t = V (x*t) (y*t)
+>     t .*^ V x y = V (x*t) (y*t)
+>     vnull = V 0 0
+>     V x1 y1 `dot` V x2 y2 = x1*y1+x2*y2
+>     V x1 y1 `cross` V x2 y2 = x1*y2-x2*y1
+>
+> instance Vector2D (Signal Vec) (Signal Float) where
+>     (^+^) = liftA2 (^+^)
+>     (^-^) = liftA2 (^-^)
+>     (^*.) = liftA2 (^*.)
+>     (.*^) = liftA2 (.*^)
+>     vnull = pure vnull
+>     dot = liftA2 dot
+>     cross = liftA2 cross
