diff --git a/doc/Breakout.html b/doc/Breakout.html
--- a/doc/Breakout.html
+++ b/doc/Breakout.html
@@ -1,5 +1,7 @@
 <!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>You can also have the program output the signal structure in <a href="http://www.graphviz.org/">Graphviz</a> dot format with the <code>--dump-dot</code> switch after the game is over. For instance, if Graphviz is installed, you can get an SVG rendition of the graph using the following command:</p><p><code>elerea-breakout --dump-dot | dot -Tsvg -o breakout.svg</code></p><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>
+</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>You can also have the program output the signal structure in <a href="http://www.graphviz.org/">Graphviz</a> dot format with the <code>--dump-dot</code> switch after the game is over. For instance, if Graphviz is installed, you can get an SVG rendition of the graph using the following command:</p><p><code>elerea-breakout --dump-dot | dot -Tsvg -o breakout.svg</code></p><p>Below follows the full source of the example.</p><pre><span class='hs-varop'>&gt;</span> <span class='hs-comment'>{-# LANGUAGE RecursiveDo #-}</span>
+<span class='hs-varop'>&gt;</span>
+<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>
@@ -7,13 +9,15 @@
 <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'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Traversable</span> <span class='hs-varid'>hiding</span> <span class='hs-layout'>(</span><span class='hs-varid'>mapM</span><span class='hs-layout'>)</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'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span><span class='hs-varop'>.</span><span class='hs-conid'>Graph</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-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Environment</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'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Unsafe</span>
+</pre>
+<pre><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>
@@ -26,10 +30,9 @@
 <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>
+</pre><p>The data structure describing the state of each 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-varop'>!</span><span class='hs-conid'>Double</span> <span class='hs-keyword'>deriving</span> <span class='hs-layout'>(</span><span class='hs-conid'>Eq</span><span class='hs-layout'>,</span><span class='hs-conid'>Show</span><span class='hs-layout'>)</span>
+</pre><p>The starting positions of the bricks.</p><pre><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-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>
@@ -52,7 +55,7 @@
 <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-keyword'>let</span> <span class='hs-varid'>game</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>breakout</span> <span class='hs-varid'>mousePosition</span> <span class='hs-varid'>windowSize</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>game</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>createSignal</span> <span class='hs-varop'>$</span> <span class='hs-varid'>breakout</span> <span class='hs-varid'>mousePosition</span> <span class='hs-varid'>windowSize</span>
 <span class='hs-varop'>&gt;</span>   <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>game</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>
@@ -63,49 +66,50 @@
 <span class='hs-varop'>&gt;</span>   <span class='hs-varid'>when</span> <span class='hs-layout'>(</span><span class='hs-str'>"--dump-dot"</span> <span class='hs-varop'>`elem`</span> <span class='hs-varid'>args</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
 <span class='hs-varop'>&gt;</span>     <span class='hs-varid'>gameGraph</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>signalToDot</span> <span class='hs-varid'>game</span>
 <span class='hs-varop'>&gt;</span>     <span class='hs-varid'>putStr</span> <span class='hs-varid'>gameGraph</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>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 through the bricks, 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 a higher-order signal, where each element of the list is a signal representing an individual brick. Bricks behave independently of each other: they are defined as separate transfer functions with the ball position as input signal. As soon as a brick is touched it enters the dying phase and fades out. Also, since other signals are mostly interested in the current state of the bricks, we have to define a flattened version, which carries the snapshots of all the brick signals. This is the <code>brickSamples</code> signal.</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-keyword'>mdo</span>
+</pre><p>User-driven player position:</p><pre><span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>let</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. We use a combination of <code>storeJust</code> and <code>toMaybe</code> to produce a latcher element that stores the value of a certain signal whenever a boolean control signal yields true.</p><pre><span class='hs-varop'>&gt;</span>   <span class='hs-varid'>ballPos</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>ballPos0</span> <span class='hs-varid'>ballVel</span>
+<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>ballVel</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>storeJust</span> <span class='hs-varid'>ballVel0</span> <span class='hs-varop'>$</span>
+<span class='hs-varop'>&gt;</span>              <span class='hs-varid'>toMaybe</span> <span class='hs-varop'>&lt;$&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'>&lt;*&gt;</span>
+<span class='hs-varop'>&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>
+</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 don&rsquo;t evaluate it at all thanks to the laziness of applicative nodes. In the end, velocity is only recalculated when a collision is detected.</p><pre><span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>let</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'>or</span> <span class='hs-varop'>.</span> <span class='hs-varid'>map</span> <span class='hs-varid'>getBrickHColl</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>brickSamples</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</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'>or</span> <span class='hs-varop'>.</span> <span class='hs-varid'>map</span> <span class='hs-varid'>getBrickVColl</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>brickSamples</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</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-keyword'>_</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-varop'>&gt;</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'>px</span> <span class='hs-varid'>playerY</span> <span class='hs-varid'>playerW</span> <span class='hs-varid'>playerH</span>
+</pre><p>Bricks are defined by the updater function <code>evolveBrick</code> as a transformer of the ball position. The transfer function takes care of fading and checking collision. Collision information is part of the state of the transfer function, even though it is strictly a function of the brick data and the ball position at the moment. However, since we need to check collisions in order to update the state of the brick, it&rsquo;s simpler and more efficient to let the outer world see the results of these checks instead of having to recalculate them.</p><pre><span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>let</span> <span class='hs-varid'>brick</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-keyglyph'>=</span> <span class='hs-varid'>transfer</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-conid'>False</span><span class='hs-layout'>,</span><span class='hs-conid'>False</span><span class='hs-layout'>)</span> <span class='hs-varid'>evolveBrick</span> <span class='hs-varid'>ballPos</span>
+<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>getBrickData</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-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-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-varop'>&gt;</span>       <span class='hs-varid'>getBrickHColl</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-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>
+<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>getBrickVColl</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-keyword'>_</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-keyglyph'>=</span> <span class='hs-varid'>c</span>
+<span class='hs-varop'>&gt;</span>       
+<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>evolveBrick</span> <span class='hs-varid'>dt</span> <span class='hs-keyword'>_</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-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-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'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-varop'>*</span><span class='hs-varid'>brickFade</span><span class='hs-layout'>)</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-varop'>&gt;</span>       <span class='hs-varid'>evolveBrick</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-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-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-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'>if</span> <span class='hs-varid'>isKilled</span> <span class='hs-keyword'>then</span> <span class='hs-conid'>Dying</span> <span class='hs-num'>1</span> <span class='hs-keyword'>else</span> <span class='hs-conid'>Live</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-varop'>&gt;</span>           <span class='hs-keyword'>where</span> <span class='hs-varid'>isKilled</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>isHit</span> <span class='hs-varop'>||</span> <span class='hs-varid'>by</span> <span class='hs-varop'>&lt;</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-varop'>&gt;</span>                 <span class='hs-varid'>isHit</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'>collHorz</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>isHit</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>isHorz</span>
+<span class='hs-varop'>&gt;</span>                 <span class='hs-varid'>collVert</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>isHit</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>not</span> <span class='hs-varid'>isHorz</span>
+<span class='hs-varop'>&gt;</span>                 <span class='hs-varid'>isHorz</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>isBrickNeeded</code> function is used to decide whether a brick should be kept in the collection. As soon as it turns false, the brick in question is removed from the <code>bricks</code> signal.</p><pre><span class='hs-varop'>&gt;</span>       <span class='hs-varid'>isBrickNeeded</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-conid'>Dying</span> <span class='hs-varid'>a</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'>a</span> <span class='hs-varop'>&gt;</span> <span class='hs-num'>0</span>
+<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>isBrickNeeded</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-conid'>Live</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-conid'>True</span>
+</pre><p>The <code>brickSamples</code> signal contains a snapshot of every brick, and it&rsquo;s obtained simply by traversing the collection (this is equivalent to rebuilding the structure with lifted constructors), then applying a sampler, which collapses the two signal layers into one. We take advantage of the fact that lists are instances of Traversable.</p><pre><span class='hs-varop'>&gt;</span>       <span class='hs-varid'>brickSamples</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>sampler</span> <span class='hs-layout'>(</span><span class='hs-varid'>sequenceA</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>bricks</span><span class='hs-layout'>)</span>
+</pre><p>The <code>bricks</code> signal carries the dynamic list of bricks along with ball-brick collision information, all of which are updated in each frame. We start out with a number of live bricks in the positions given by the <code>brickPos0</code> list, and derive the list of the next frame from the current one by filtering out the bricks for which <code>isBrickNeeded</code> evaluates to false. These updates are made explicit by using <code>delay</code> to define the dynamic collection.</p><pre><span class='hs-varop'>&gt;</span>   <span class='hs-varid'>bricks</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-keyword'>do</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>bricksInit</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>mapM</span> <span class='hs-varid'>brick</span> <span class='hs-varid'>brickPos0</span>
+<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>let</span> <span class='hs-varid'>bricksNext</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>snd</span> <span class='hs-varop'>.</span> <span class='hs-varid'>filter</span> <span class='hs-layout'>(</span><span class='hs-varid'>isBrickNeeded</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fst</span><span class='hs-layout'>)</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>zip</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>brickSamples</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-varid'>delay</span> <span class='hs-varid'>bricksInit</span> <span class='hs-varid'>bricksNext</span>
+</pre><p>And knowing all these signals we can finally assemble the signal of rendering actions, i.e.&nbsp;the animation:</p><pre><span class='hs-varop'>&gt;</span>   <span class='hs-varid'>return</span> <span class='hs-varop'>$</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'>map</span> <span class='hs-varid'>getBrickData</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>brickSamples</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>
diff --git a/doc/Chase.html b/doc/Chase.html
--- a/doc/Chase.html
+++ b/doc/Chase.html
@@ -1,5 +1,7 @@
 <!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>
+</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-comment'>{-# LANGUAGE RecursiveDo #-}</span>
+<span class='hs-varop'>&gt;</span>
+<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>
@@ -23,13 +25,18 @@
 <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-varid'>greyPos</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>createSignal</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>mdo</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>mouseClick</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>edge</span> <span class='hs-varid'>mousePress</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-keyword'>let</span> <span class='hs-varid'>acc</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'>pos</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-varid'>pos</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>vnull</span> <span class='hs-varid'>vel</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>vel0</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>vnull</span> <span class='hs-varid'>acc</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>vel</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>sampler</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>storeJust</span> <span class='hs-varid'>vel0</span> <span class='hs-varop'>.</span> <span class='hs-varid'>generator</span> <span class='hs-varid'>mouseClick</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'>vel</span><span class='hs-varop'>^+^</span><span class='hs-varid'>pos</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'>acc</span><span class='hs-layout'>)</span>
+<span class='hs-varop'>&gt;</span>
+<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>return</span> <span class='hs-varid'>pos</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'>greyPos</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>
diff --git a/doc/Makefile b/doc/Makefile
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -2,7 +2,7 @@
 
 PANDOC := pandoc --no-wrap -s -S
 HSCOLOUR := HsColour -lit
-UNIOPS := sed "s/>&lt;-</>\&larr;</g" | sed "s/>-&gt;</>\&rarr;</g"
+UNIOPS := sed "s/>&lt;-</>\&larr;</g" | sed "s/>-&gt;</>\&rarr;</g" | sed "s/varid'>mdo/keyword'>mdo/g"
 
 all: ../src/Breakout.html ../src/Chase.html
 
diff --git a/elerea-examples.cabal b/elerea-examples.cabal
--- a/elerea-examples.cabal
+++ b/elerea-examples.cabal
@@ -1,5 +1,5 @@
 Name:                elerea-examples
-Version:             0.3.0
+Version:             1.0.0
 Cabal-Version:       >= 1.2
 Synopsis:            Example applications for Elerea
 Category:            reactivity, FRP
@@ -41,12 +41,12 @@
   Executable:        elerea-breakout
   HS-Source-Dirs:    src
   Main-IS:           Breakout.lhs
-  Build-Depends:     base, elerea >= 0.3, OpenGL, GLFW
+  Build-Depends:     base >= 3 && < 5, elerea >= 1.0, OpenGL, GLFW
   GHC-Options:       -O2
 
 Executable elerea-chase
   Executable:        elerea-chase
   HS-Source-Dirs:    src
   Main-IS:           Chase.lhs
-  Build-Depends:     base, elerea >= 0.2, OpenGL, GLFW
+  Build-Depends:     base >= 3 && < 5, elerea >= 1.0, OpenGL, GLFW
   GHC-Options:       -O2
diff --git a/src/Breakout.lhs b/src/Breakout.lhs
--- a/src/Breakout.lhs
+++ b/src/Breakout.lhs
@@ -31,6 +31,8 @@
 
 Below follows the full source of the example.
 
+> {-# LANGUAGE RecursiveDo #-}
+>
 > module Main where
 > 
 > import Control.Applicative
@@ -39,12 +41,14 @@
 > import Data.IORef
 > import Data.List
 > import Data.Maybe
+> import Data.Traversable hiding (mapM)
 > import FRP.Elerea
 > import FRP.Elerea.Graph
 > import Graphics.UI.GLFW as GLFW
 > import Graphics.Rendering.OpenGL
 > import System.Environment
-> 
+> import System.IO.Unsafe
+
 > import Common.Utils
 > import Common.Vector
 
@@ -78,14 +82,16 @@
 > 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.
+The data structure describing the state of each 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
->
+> data BrickState = Live | Dying !Double deriving (Eq,Show)
+
+The starting positions of the bricks.
+
 > 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) |
+>     where distributeBricks xmin ymin xmax ymax xn yn = [(xmin+xstep*x,ymin+ystep*y) |
 >                                                         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
@@ -124,7 +130,7 @@
 > 
 >   -- All we need to get going is an IO-valued signal and an IO
 >   -- function to update the external signals
->   let game = breakout mousePosition windowSize
+>   game <- createSignal $ breakout mousePosition windowSize
 >   driveNetwork game (readInput mousePositionSink closed)
 > 
 >   -- The inevitable sad ending
@@ -147,46 +153,49 @@
 * `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 position and velocity of the ball form a circular dependency
+through the bricks, 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.
+The signal carrying the collection of the bricks is a higher-order
+signal, where each element of the list is a signal representing an
+individual brick.  Bricks behave independently of each other: they are
+defined as separate transfer functions with the ball position as input
+signal.  As soon as a brick is touched it enters the dying phase and
+fades out.  Also, since other signals are mostly interested in the
+current state of the bricks, we have to define a flattened version,
+which carries the snapshots of all the brick signals.  This is the
+`brickSamples` signal.
 
-> breakout mousePos windowSize = renderLevel <$> playerX <*> ballPos <*> (getBricks <$> bricks)
->     where 
+> breakout mousePos windowSize = mdo
 
 User-driven player position:
 
->           playerX = adjustPlayerPos <$> mousePos <*> windowSize
->           adjustPlayerPos (V x _) (V w _) = min (fieldW-playerW) $ max (-fieldW) $ 2*x/w-1-playerW/2
+>   let 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.
+Ball state: position and velocity.  We use a combination of
+`storeJust` and `toMaybe` to produce a latcher element that stores the
+value of a certain signal whenever a boolean control signal yields
+true.
 
->           ballPos = integralVec (ballPos0) ballVel
->           ballVel = latcher (pure ballVel0)
->                             (ballCollHorz ||@ ballCollVert ||@ ballCollPlayer)
->                             (pure <$> (adjustVel <$> ballCollHorz <*> ballCollVert <*> ballCollPlayer <*>
->                                        ballVel <*> ballNewVelX))
+>   ballPos <- integralVec ballPos0 ballVel
+>   ballVel <- storeJust ballVel0 $
+>              toMaybe <$> (ballCollHorz ||@ ballCollVert ||@ ballCollPlayer) <*>
+>                          (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.
+we don't evaluate it at all thanks to the laziness of applicative
+nodes.  In the end, velocity is only recalculated when a collision is
+detected.
 
->           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)
+>   let 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
@@ -194,46 +203,73 @@
 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
->
+>       ballCollHorz = (or . map getBrickHColl <$> brickSamples)
+>                      ||@ (check <$> ballPos <*> ballVel)
+>           where check (V bx _) (V bvx _) = (bx < -fieldW && bvx < 0) ||
+>                                            (bx > fieldW-ballW && bvx > 0)
+>       ballCollVert = (or . map getBrickVColl <$> brickSamples)
+>                      ||@ (check <$> ballPos <*> ballVel)
+>           where check (V _ 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 are defined by the updater function `evolveBrick` as a
+transformer of the ball position.  The transfer function takes care of
+fading and checking collision.  Collision information is part of the
+state of the transfer function, even though it is strictly a function
+of the brick data and the ball position at the moment.  However, since
+we need to check collisions in order to update the state of the brick,
+it's simpler and more efficient to let the outer world see the results
+of these checks instead of having to recalculate them.
 
->           bricks = transfer (False,False,brickPos0) updateBricks ballPos
->           getBricks (_,_,bs) = bs
->           getHColl (c,_,_) = c
->           getVColl (_,c,_) = c
+>   let brick (x,y) = transfer (x,y,Live,False,False) evolveBrick ballPos
+>       getBrickData (x,y,s,_,_) = (x,y,s)
+>       getBrickHColl (_,_,_,c,_) = c
+>       getBrickVColl (_,_,_,_,c) = c
+>       
+>       evolveBrick dt _   (x,y,Dying a,_,_) = (x,y,Dying (a-realToFrac dt*brickFade),False,False)
+>       evolveBrick dt (V bx by) (x,y,_,_,_) = (x,y,if isKilled then Dying 1 else Live,collHorz,collVert)
+>           where isKilled = isHit || by < -fieldH-ballH
+>                 isHit = doRectsIntersect bx by ballW ballH x y brickW brickH
+>                 collHorz = isHit && isHorz
+>                 collVert = isHit && not isHorz
+>                 isHorz = xDist/brickW > yDist/brickH
+>                     where xDist = abs ((x+brickW/2)-(bx+ballW/2))
+>                           yDist = abs ((y+brickH/2)-(by+ballH/2))
 
-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.
+The `isBrickNeeded` function is used to decide whether a brick should
+be kept in the collection.  As soon as it turns false, the brick in
+question is removed from the `bricks` signal.
 
->           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))
+>       isBrickNeeded (_,_,Dying a,_,_) = a > 0
+>       isBrickNeeded (_,_,Live   ,_,_) = True
+
+The `brickSamples` signal contains a snapshot of every brick, and it's
+obtained simply by traversing the collection (this is equivalent to
+rebuilding the structure with lifted constructors), then applying a
+sampler, which collapses the two signal layers into one.  We take
+advantage of the fact that lists are instances of Traversable.
+
+>       brickSamples = sampler (sequenceA <$> bricks)
+
+The `bricks` signal carries the dynamic list of bricks along with
+ball-brick collision information, all of which are updated in each
+frame.  We start out with a number of live bricks in the positions
+given by the `brickPos0` list, and derive the list of the next frame
+from the current one by filtering out the bricks for which
+`isBrickNeeded` evaluates to false.  These updates are made explicit
+by using `delay` to define the dynamic collection.
+
+>   bricks <- do
+>     bricksInit <- mapM brick brickPos0
+>     let bricksNext = map snd . filter (isBrickNeeded . fst) <$> (zip <$> brickSamples <*> bricks)
+>     delay bricksInit bricksNext
+
+And knowing all these signals we can finally assemble the signal of
+rendering actions, i.e. the animation:
+
+>   return $ renderLevel <$> playerX <*> ballPos <*> (map getBrickData <$> brickSamples)
 
 The `doRectsIntersect` function decides whether two rectangles defined
 by their top left corners and dimensions overlap.
diff --git a/src/Chase.lhs b/src/Chase.lhs
--- a/src/Chase.lhs
+++ b/src/Chase.lhs
@@ -9,6 +9,8 @@
 
 For a slightly more complex example check out `Breakout.lhs`.
 
+> {-# LANGUAGE RecursiveDo #-}
+>
 > module Main where
 > 
 > import Control.Applicative
@@ -39,13 +41,18 @@
 >   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
+>   greyPos <- createSignal $ mdo
+>         mouseClick <- edge mousePress
 >
->   driveNetwork (render <$> windowSize <*> mousePosition <*> ballPos)
+>         let acc = (mousePosition^-^pos)^*.0.3
+>         pos <- integralVec vnull vel
+>         vel0 <- integralVec vnull acc
+>         vel <- sampler <$> (storeJust vel0 . generator mouseClick)
+>                (integralVec <$> vel^+^pos^-^mousePosition <*> pure acc)
+>
+>         return pos
+>
+>   driveNetwork (render <$> windowSize <*> mousePosition <*> greyPos)
 >                (readInput mousePositionSink mousePressSink closed)
 > 
 >   closeWindow
