packages feed

elerea-examples-2.2.2: doc/Chase.html

<!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" />
  <meta name="date" content="" />
  <link rel="stylesheet" href="hscolour.css" type="text/css" />
</head>
<body>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ --><title>Haskell code</title> <link type='text/css' rel='stylesheet' href='hscolour.css' /></head>
<body><div id="elerea-chase-example"
><h1
  >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 DoRec #-}</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'>Monad</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>IORef</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span><span class='hs-varop'>.</span><span class='hs-conid'>Param</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>UI</span><span class='hs-varop'>.</span><span class='hs-conid'>GLFW</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>GLFW</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>Rendering</span><span class='hs-varop'>.</span><span class='hs-conid'>OpenGL</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span>
</pre><p
  >The <code
    >main</code
    > function contains the whole reactive logic. Note that <code
    >driveNetwork</code
    > is just a simple loop, and you can see its source below in the <code
    >Utils</code
    > module.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>main</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>initialize</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>openWindow</span> <span class='hs-layout'>(</span><span class='hs-conid'>Size</span> <span class='hs-num'>640</span> <span class='hs-num'>480</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>DisplayRGBBits</span> <span class='hs-num'>8</span> <span class='hs-num'>8</span> <span class='hs-num'>8</span><span class='hs-layout'>,</span> <span class='hs-conid'>DisplayAlphaBits</span> <span class='hs-num'>8</span><span class='hs-layout'>,</span> <span class='hs-conid'>DisplayDepthBits</span> <span class='hs-num'>24</span><span class='hs-keyglyph'>]</span> <span class='hs-conid'>Window</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>windowTitle</span> <span class='hs-varop'>$=</span> <span class='hs-str'>"Elerea Chase"</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varid'>windowSize</span><span class='hs-layout'>,</span><span class='hs-varid'>windowSizeSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-varid'>vnull</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varid'>mousePosition</span><span class='hs-layout'>,</span><span class='hs-varid'>mousePositionSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-varid'>vnull</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varid'>mousePress</span><span class='hs-layout'>,</span><span class='hs-varid'>mousePressSink</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>external</span> <span class='hs-conid'>False</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>newIORef</span> <span class='hs-conid'>False</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>windowSizeCallback</span> <span class='hs-varop'>$=</span> <span class='hs-varid'>resizeGLScene</span> <span class='hs-varid'>windowSizeSink</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>windowCloseCallback</span> <span class='hs-varop'>$=</span> <span class='hs-layout'>(</span><span class='hs-varid'>writeIORef</span> <span class='hs-varid'>closed</span> <span class='hs-conid'>True</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>True</span><span class='hs-layout'>)</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-varid'>network</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>start</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</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-varid'>rec</span> <span class='hs-keyword'>let</span> <span class='hs-varid'>newVel</span> <span class='hs-varid'>clk</span> <span class='hs-varid'>v0</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>clk</span> <span class='hs-keyword'>of</span>
<span class='hs-varop'>&gt;</span>                     <span class='hs-conid'>True</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>v0</span> <span class='hs-varid'>acc</span>
<span class='hs-varop'>&gt;</span>                     <span class='hs-conid'>False</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>Nothing</span>
<span class='hs-varop'>&gt;</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'>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'>vels</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>storeJust</span> <span class='hs-varid'>vel0</span> <span class='hs-varop'>=&lt;&lt;</span> <span class='hs-varid'>generator</span> <span class='hs-layout'>(</span><span class='hs-varid'>newVel</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>mouseClick</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-layout'>)</span>
<span class='hs-varop'>&gt;</span>             <span class='hs-varid'>vel</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>delay</span> <span class='hs-varid'>vnull</span> <span class='hs-layout'>(</span><span class='hs-varid'>join</span> <span class='hs-varid'>vels</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>             <span class='hs-varid'>pos</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>delay</span> <span class='hs-varid'>vnull</span> <span class='hs-varop'>=&lt;&lt;</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-varop'>&gt;</span>         <span class='hs-varid'>return</span> <span class='hs-varop'>$</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'>pos</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>network</span> <span class='hs-layout'>(</span><span class='hs-varid'>readInput</span> <span class='hs-varid'>mousePositionSink</span> <span class='hs-varid'>mousePressSink</span> <span class='hs-varid'>closed</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>closeWindow</span>
</pre><p
  >The <code
    >render</code
    > function takes a snapshot of the system (window size and the positions of the squares) and turns it into OpenGL calls. The signal executed by the <code
    >driveNetwork</code
    > function is the time-varying version of the IO action returned here.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>render</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>w</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>cx</span> <span class='hs-varid'>cy</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-varid'>ox</span> <span class='hs-varid'>oy</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>let</span> <span class='hs-varid'>drawSquare</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>loadIdentity</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>translate</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vector3</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>/</span><span class='hs-varid'>w</span><span class='hs-varop'>*</span><span class='hs-num'>2</span><span class='hs-comment'>-</span><span class='hs-num'>1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>h</span><span class='hs-varop'>/</span><span class='hs-varid'>w</span><span class='hs-comment'>-</span><span class='hs-varid'>y</span><span class='hs-varop'>/</span><span class='hs-varid'>w</span><span class='hs-varop'>*</span><span class='hs-num'>2</span><span class='hs-layout'>)</span> <span class='hs-num'>0</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>renderPrimitive</span> <span class='hs-conid'>Quads</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>vertex</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Vertex3</span> <span class='hs-layout'>(</span><span class='hs-comment'>-</span><span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>clear</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>ColorBuffer</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>1</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-num'>0.5</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>drawSquare</span> <span class='hs-varid'>cx</span> <span class='hs-varid'>cy</span> <span class='hs-num'>0.05</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>color</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>1</span> <span class='hs-num'>1</span> <span class='hs-num'>1</span> <span class='hs-layout'>(</span><span class='hs-num'>0.6</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>drawSquare</span> <span class='hs-varid'>ox</span> <span class='hs-varid'>oy</span> <span class='hs-num'>0.03</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>flush</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>swapBuffers</span>
</pre><p
  >The <code
    >readInput</code
    > function provides the driver layer. It feeds the peripheral-bound signals and also decides when to stop execution by returning <code
    >Nothing</code
    > instead of the time elapsed since its last call.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>readInput</span> <span class='hs-varid'>mousePos</span> <span class='hs-varid'>mouseBut</span> <span class='hs-varid'>closed</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>t</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>get</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>time</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>time</span> <span class='hs-varop'>$=</span> <span class='hs-num'>0</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-conid'>Position</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>get</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>mousePos</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>mousePos</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>b</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-varid'>getMouseButton</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-conid'>ButtonLeft</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>mouseBut</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-varop'>==</span> <span class='hs-conid'>GLFW</span><span class='hs-varop'>.</span><span class='hs-conid'>Press</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>k</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>getKey</span> <span class='hs-conid'>ESC</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>readIORef</span> <span class='hs-varid'>closed</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-keyword'>if</span> <span class='hs-varid'>c</span> <span class='hs-varop'>||</span> <span class='hs-varid'>k</span> <span class='hs-varop'>==</span> <span class='hs-conid'>Press</span> <span class='hs-keyword'>then</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span>
</pre><p
  >OpenGL is initialised with practically everything turned off. Only alpha blending is needed to be able to use translucent colours.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>initGL</span> <span class='hs-varid'>width</span> <span class='hs-varid'>height</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>clearColor</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Color4</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>1</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>blend</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Enabled</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>blendFunc</span> <span class='hs-varop'>$=</span> <span class='hs-layout'>(</span><span class='hs-conid'>SrcAlpha</span><span class='hs-layout'>,</span><span class='hs-conid'>OneMinusSrcAlpha</span><span class='hs-layout'>)</span>
</pre><p
  >The window size callback takes care of the <code
    >windowSize</code
    > signal and the projection matrix.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>resizeGLScene</span> <span class='hs-varid'>winSize</span> <span class='hs-varid'>size</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>Size</span> <span class='hs-varid'>w</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>winSize</span> <span class='hs-layout'>(</span><span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>w</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>viewport</span> <span class='hs-varop'>$=</span> <span class='hs-layout'>(</span><span class='hs-conid'>Position</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span><span class='hs-layout'>,</span><span class='hs-varid'>size</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>matrixMode</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Projection</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>loadIdentity</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>scale</span> <span class='hs-num'>1</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>w</span><span class='hs-varop'>/</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>h</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-num'>1</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>matrixMode</span> <span class='hs-varop'>$=</span> <span class='hs-conid'>Modelview</span> <span class='hs-num'>0</span>
</pre></div
><div id="utils-module"
><h1
  >Utils module</h1
  ><p
  >This module contains some functions that might make it into the core library eventually.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span> <span class='hs-keyword'>where</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span><span class='hs-varop'>.</span><span class='hs-conid'>Param</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span>
</pre><p
  >The <code
    >driveNetwork</code
    > function simply executes the supersteps while the <code
    >driver</code
    > function keeps returning valid delta time values.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>network</span> <span class='hs-varid'>driver</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>dt</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>driver</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-keyword'>case</span> <span class='hs-varid'>dt</span> <span class='hs-keyword'>of</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>Just</span> <span class='hs-varid'>dt</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-keyword'>do</span> <span class='hs-varid'>join</span> <span class='hs-layout'>(</span><span class='hs-varid'>network</span> <span class='hs-varid'>dt</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>                   <span class='hs-varid'>driveNetwork</span> <span class='hs-varid'>network</span> <span class='hs-varid'>driver</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
</pre><p
  >A scalar integral function for <code
    >Fractional</code
    > instances.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>integral</span> <span class='hs-varid'>v0</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-varid'>v0</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>v</span> <span class='hs-varid'>v0</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v0</span><span class='hs-varop'>+</span><span class='hs-varid'>v</span><span class='hs-varop'>*</span><span class='hs-varid'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
</pre><p
  >An integral function for two-dimensional vectors defined in the <code
    >Vector</code
    > module.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>integralVec</span> <span class='hs-varid'>v0</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-varid'>v0</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>dt</span> <span class='hs-varid'>v</span> <span class='hs-varid'>v0</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v0</span><span class='hs-varop'>^+^</span><span class='hs-layout'>(</span><span class='hs-varid'>v</span><span class='hs-varop'>^*.</span><span class='hs-varid'>realToFrac</span> <span class='hs-varid'>dt</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
</pre><p
  >A rising edge detector.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>edge</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>s'</span> <span class='hs-keyglyph'>&larr;</span> <span class='hs-varid'>delay</span> <span class='hs-conid'>False</span> <span class='hs-varid'>s</span>
<span class='hs-varop'>&gt;</span>   <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>s'</span> <span class='hs-varop'>&gt;&gt;=</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>x</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-keyword'>if</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-conid'>False</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>s</span>
</pre><p
  >A latch that always remembers the last value of a <code
    >Maybe</code
    > signal wrapped in <code
    >Just</code
    >.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-varid'>storeJust</span> <span class='hs-varid'>x0</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>transfer</span> <span class='hs-varid'>x0</span> <span class='hs-varid'>store</span> <span class='hs-varid'>s</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>where</span> <span class='hs-varid'>store</span> <span class='hs-keyword'>_</span> <span class='hs-conid'>Nothing</span>  <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span>
<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>store</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span>
</pre></div
><div id="vector-module"
><h1
  >Vector module</h1
  ><p
  >This module contains a class for two-dimensional vectors, a strict datatype to instantiate it, and another instance for signals of the same type.</p
  ><pre><span class='hs-varop'>&gt;</span> <span class='hs-comment'>{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, TypeSynonymInstances #-}</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Vector</span> <span class='hs-keyword'>where</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>FRP</span><span class='hs-varop'>.</span><span class='hs-conid'>Elerea</span><span class='hs-varop'>.</span><span class='hs-conid'>Param</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Graphics</span><span class='hs-varop'>.</span><span class='hs-conid'>Rendering</span><span class='hs-varop'>.</span><span class='hs-conid'>OpenGL</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>data</span> <span class='hs-conid'>Vec</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>{</span> <span class='hs-varid'>getX</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>!</span><span class='hs-conid'>GLfloat</span><span class='hs-layout'>,</span> <span class='hs-varid'>getY</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>!</span><span class='hs-conid'>GLfloat</span> <span class='hs-layout'>}</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>^*.</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>.*^</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>`dot`</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>7</span> <span class='hs-varop'>`cross`</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>6</span> <span class='hs-varop'>^+^</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>infixl</span> <span class='hs-num'>6</span> <span class='hs-varop'>^-^</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>class</span> <span class='hs-conid'>Vector2D</span> <span class='hs-varid'>v</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span> <span class='hs-keyword'>where</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>dot</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>cross</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>&rarr;</span> <span class='hs-varid'>c</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>instance</span> <span class='hs-conid'>Vector2D</span> <span class='hs-conid'>Vec</span> <span class='hs-conid'>GLfloat</span> <span class='hs-keyword'>where</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>^+^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-varop'>+</span><span class='hs-varid'>x2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y1</span><span class='hs-varop'>+</span><span class='hs-varid'>y2</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>^-^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x1</span><span class='hs-comment'>-</span><span class='hs-varid'>x2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y1</span><span class='hs-comment'>-</span><span class='hs-varid'>y2</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-varop'>^*.</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>t</span> <span class='hs-varop'>.*^</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>y</span><span class='hs-varop'>*</span><span class='hs-varid'>t</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>V</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>`dot`</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x1</span><span class='hs-varop'>*</span><span class='hs-varid'>y1</span><span class='hs-varop'>+</span><span class='hs-varid'>x2</span><span class='hs-varop'>*</span><span class='hs-varid'>y2</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-conid'>V</span> <span class='hs-varid'>x1</span> <span class='hs-varid'>y1</span> <span class='hs-varop'>`cross`</span> <span class='hs-conid'>V</span> <span class='hs-varid'>x2</span> <span class='hs-varid'>y2</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x1</span><span class='hs-varop'>*</span><span class='hs-varid'>y2</span><span class='hs-comment'>-</span><span class='hs-varid'>x2</span><span class='hs-varop'>*</span><span class='hs-varid'>y1</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>instance</span> <span class='hs-conid'>Vector2D</span> <span class='hs-layout'>(</span><span class='hs-conid'>Signal</span> <span class='hs-conid'>Vec</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Signal</span> <span class='hs-conid'>GLfloat</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^+^</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^-^</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>^*.</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-layout'>(</span><span class='hs-varop'>.*^</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>vnull</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pure</span> <span class='hs-varid'>vnull</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>dot</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-varid'>dot</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>cross</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>liftA2</span> <span class='hs-varid'>cross</span>
</pre></body>
</html>

</div
>
</body>
</html>