<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Data.Random</title>
	<atom:link href="http://random.axman6.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://random.axman6.com/blog</link>
	<description>Random mutterings about life and Haskell.</description>
	<lastBuildDate>Fri, 06 Jul 2012 05:21:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Exploring CPU design using Haskell</title>
		<link>http://random.axman6.com/blog/?p=327</link>
		<comments>http://random.axman6.com/blog/?p=327#comments</comments>
		<pubDate>Fri, 06 Jul 2012 05:21:54 +0000</pubDate>
		<dc:creator>axman6</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[CPU Design]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Kansas-lava]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=327</guid>
		<description><![CDATA[For some time now, I&#8217;ve been thinking about designing my own CPU architecture. Last week, I couldn&#8217;t get the thought out of my head, and I finally gave in and started to really think about what I&#8217;d want from a moderately simple CPU. I&#8217;ve decided that I&#8217;m going to document the process as I go, [...]]]></description>
			<content:encoded><![CDATA[<p>For some time now, I&#8217;ve been thinking about designing my own CPU architecture. Last week, I couldn&#8217;t get the thought out of my head, and I finally gave in and started to really think about what I&#8217;d want from a moderately simple CPU. I&#8217;ve decided that I&#8217;m going to document the process as I go, to hopefully force myself to finish this project; I&#8217;m often quite bad at starting something I find fun, and losing interest before I get to something I&#8217;d call complete. I am hoping to change this&#8230; I really hope a future potential employers don&#8217;t read this bit&#8230;</p>

<p>My aim for this project is to have something I can actually run programs on, and maybe even get an LLVM backend written so I can compile basic C programs for it. I plan to implement all the hardware design using the Haskell library Kansas Lava, which allows for designing hardware which can be both simulated in Haskell (you can play with most circuits in GHCI, which is amazingly nice), as well as produce VHDL which can be synthesised and used to configure things like an FPGA. My goal is to have this design running on my <a href="http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,792&amp;Prod=S3EBOARD">Spartan-3E FPGA Starter Board</a>, or possibly one of <a href="http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,819&amp;Prod=GENESYS">these</a> (due to its 64bit wide memory interface). So, on to the design!</p>

<p>Obviously it has to be RISC; my skills in hardware design are rusty enough without me having to figure out how to parse binary data in hardware, and besides, no one uses CISC any more these days, they only pretend. But just saying it&#8217;s RISC doesn&#8217;t get me far, and I only had a vague idea of what I wanted to be able to do. There were lots of features from ARM that I wanted:</p>

<ul>
<li><p>(Almost) all instructions are conditional, which can make for some very efficient code, both in terms of speed and space required.</p></li>
<li><p>Lots of registers. Well, I guess 16 is lots, but I wanted more.</p></li>
<li><p>Most arithmetic instructions have free shifts on their second argument, so there&#8217;s no need for dedicated shift instructions. This is pretty neat, and I decided I wanted more free stuff! We&#8217;ll get to that in my next post.</p></li>
</ul>

<p>There were also some other architectures that intrigued me, notably SPARC.</p>

<ul>
<li><p>A register set to constant zero, useful for simplifying many operations. Sometimes you want to perform a computation, but you only care about some of its side effects, such as whether it overflows. You can just use this register as the destination, and the result will be lost, but the side effects wont. Also there&#8217;s no need for a negation instruction, since it&#8217;s just subtracting x from zero.</p></li>
<li><p>A register window. On function calls, the registers available to new function are not the same as those of calling function, but there is an overlap of 8 registers, which is where the first 8 (I think) function arguments are passed. When the function returns, the window slides back, and the result will have been passed back in what are now the top 8 registers. I decided this is not a feature I need, because&#8230; it seems complicated to implement, and the advantages in such a simple design as mine aren&#8217;t really worth it as far as I can tell.</p></li>
<li><p>A branch delay slot. ARM also has this, but I&#8217;d forgotten about it during my initial thinking, and realised it would be a useful thing to have to make implementation easier. Essentially what this means is that when a branch instruction is executed, the instruction immediately following it is executed before the branch actually occurs. In a pipelined architecture, this can be quite useful, it can help avoid pipeline stalls. I think one of the main reasons for them existing is due to the extra time needed to fetch the next instruction in order to execute it. The CPU could either stall for a cycle (or more) waiting for it, or it could do some useful work in the mean time.</p></li>
</ul>

<p>So with this I got started. I decided, somewhat arbitrarily, that I wanted this to be a 64 bit architecture, with 64 bit wide instructions. This choice would allow me to have more registers than architectures like ARM. It also meant I had more room for constants in instructions, making a lot of tasks easier, and avoiding memory accesses for almost all constants (I&#8217;ve ended up with constants up to 36 bits). Initially I was going to go all out, and have 256 64bit registers, but I figured this was a bit of a waste, and I eventually decided (again, somewhat arbitrarily) on 64 registers (plus some special purpose ones).</p>

<p>I also really wanted conditional execution of instructions, and almost all instructions will be conditional. For those not in the know, this means that the instruction&#8217;s result is only executed if certain condition flags are set. This can lead to some extremely efficient branchless code, where in the past you would have had to jump between the two clauses of an if-else statement, now you can just perform the comparison, and have all the instructions from each execute conditionally. Sure you waste a few cycles, but you won&#8217;t stall the pipeline, and it usually means having less instructions in the code.</p>

<p>Next I started to think about what operations my CPU would need, and what I would like on top of the basics. A came up with a list of basic arithmetic instructions:</p>

<table>
<caption id="arithmeticinstructions">Arithmetic instructions</caption>
<col />
<col />
<thead>
<tr>
    <th>Instruction</th>
    <th>Description</th>
</tr>
</thead>
<tbody>
<tr>
    <td>add{c}{s}</td>
    <td>Addition of 64bit two&#8217;s complement numbers</td>
</tr>
<tr>
    <td>sub{c}{s}</td>
    <td>Subtract</td>
</tr>
<tr>
    <td>rsub{c}{s}</td>
    <td>Subtract with arguments reversed. The reason for the inclusion of this will become apparent soon int my next post.</td>
</tr>
<tr>
    <td>mul{s}</td>
    <td>Multiply</td>
</tr>
<tr>
    <td>mula{s}</td>
    <td>Multiply and accumulate. <code>res = res + a*b</code></td>
</tr>
<tr>
    <td>addsat{s}</td>
    <td>Saturating addition (Because ARM has it, and it seemed nifty)</td>
</tr>
<tr>
    <td>padd{32,16,8}</td>
    <td>Parallel addition</td>
</tr>
<tr>
    <td>psub{32,16,8}</td>
    <td>Parallel subtraction</td>
</tr>
<tr>
    <td>pmul{32,16,8}</td>
    <td>Parallel multiplication</td>
</tr>
<tr>
    <td> </td>
    <td> </td>
</tr>
<tr>
    <td>and{s}</td>
    <td>Bitwise and</td>
</tr>
<tr>
    <td>or{s}</td>
    <td>Bitwise or</td>
</tr>
<tr>
    <td>xor{s}</td>
    <td>Bitwise exclusive or</td>
</tr>
<tr>
    <td>nand{s}</td>
    <td>Bitwise not-and</td>
</tr>
<tr>
    <td>nor{s}</td>
    <td>Bitwise not-or</td>
</tr>
<tr>
    <td> </td>
    <td> </td>
</tr>
<tr>
    <td>cmp</td>
    <td>Comparison (<code>cmp rm op2</code> is an alias for <code>subs r0 rm op2</code>)</td>
</tr>
<tr>
    <td> </td>
    <td> </td>
</tr>
<tr>
    <td>max{,32,16,8}{s}</td>
    <td>Maximum</td>
</tr>
<tr>
    <td>min{,32,16,8}{s}</td>
    <td>Minimum</td>
</tr>
</tbody>
</table>

<p>The things in curly brackets are variants of the instruction. Instructions with the <code>{s}</code> variant mean they can set the condition flags based on their result, for example, <code>adds</code> can set the carry flag indicating that the addition had a carry out past the end of the result. Instructions with a <code>{c}</code> variant (ie <code>addc</code>) will perform their operation using the carry flag as an input, in whatever manner makes sense for the given instruction. For example, to add two 128 bit numbers in registers r10, 11 and r20, r21 with the result going into r30, r31, you might use something like:</p>

<p><pre><code>adds r30, r10, r20; # Add, setting flags (ie carry)
addc r31, r11, r21; # Add, using the previously set carried bit
</code></pre></p>

<p>Instructions with sizes after them, as you might expect, operate on differing sized inputs. <code>padd</code> can add 2&#215;32bit numbers, 4&#215;16bit, or 8&#215;8bit.</p>

<p>Then there&#8217;s the branching instructions. Since almost all instructions will be conditional, I only really need two kinds of branches. A standard branch, which covers all types of conditional branches automatically, and some kind of call instruction, which would not only modify the program counter, but also save the return address somewhere. There would also need to be its dual, a return instruction, which sets the program counter to the value that was previously saved.</p>

<table>
<caption id="branchinginstructions">Branching instructions</caption>
<col />
<col />
<thead>
<tr>
    <th>Instruction</th>
    <th>Description</th>
</tr>
</thead>
<tbody>
<tr>
    <td>br</td>
    <td>Normal branch, <code>pc &lt;- src shiftL 3</code></td>
</tr>
<tr>
    <td>call</td>
    <td>Function call, otherwise known as branch and link on ARM. <code>ra &lt;- (pc shiftR 3)+1; pc &lt;- src shiftL 3</code></td>
</tr>
<tr>
    <td>ret</td>
    <td>Function return. <code>pc &lt;- ra shiftL 3</code></td>
</tr>
</tbody>
</table>

<p>There&#8217;s some odd stuff going on here, so I&#8217;ll explain. The shifts by three come from me wanting to ensure that instructions are always word aligned. Also doing this means that we can jump to constants 8 times further away than previously possible. In the call instruction, we save the address of the next instruction to the return address register, and set the program counter to the address given to the instruction. Each function is responsible for saving the ra if it&#8217;s going to make another function call, and restoring it before returning to its callee.</p>

<p>So far we&#8217;ve got enough to be a sorta, kinda, maybe turing complete (assuming infinite registers&#8230;) machine, but there&#8217;s something quite important missing: memory access. This is something I have less planned out than the other forms of instructions, since I&#8217;m not sure what sort of features would be really useful, so more time will have to spent on this before I come up with a final design. What I have so far in terms of instructions are:</p>

<table>
<caption id="loadstoreinstructions">Load/Store instructions</caption>
<col />
<col />
<thead>
<tr>
    <th>Instruction</th>
    <th>Description</th>
</tr>
</thead>
<tbody>
<tr>
    <td>ld{,32,16,8}</td>
    <td>Load a {64,32,15,8}bit value from memory into a register. <code>rdest &lt;- mem[src]</code></td>
</tr>
<tr>
    <td>st{,32,16,8}</td>
    <td>Store   <code>mem[dst] &lt;- rsrc</code></td>
</tr>
<tr>
    <td>ldsp{,32,16,8}</td>
    <td>Load relative to stack pointer (Frame pointer?)</td>
</tr>
<tr>
    <td>stsp{,32,16,8}</td>
    <td>Store relative to stack pointer</td>
</tr>
<tr>
    <td>push{,32,16,8}</td>
    <td>Push a value onto the stack   <code>[sp] &lt;- rsrc; sp &lt;- sp - {8,4,2,1}</code></td>
</tr>
<tr>
    <td>pop{,32,16,8}</td>
    <td>Pop a value off the stack   <code>rdest &lt;- [sp]; sp &lt;- sp + {8,4,2,1}</code></td>
</tr>
</tbody>
</table>

<p>Here we have some pretty standard instruction, though the push and pop are maybe not in some RISC architectures because they&#8217;re easy to implement if you have direct access to the stack as a general purpose register. I haven&#8217;t decided whether I&#8217;ll do this or not, but I think it&#8217;s likely, since one day, it might be really useful to be able to swap stacks easily (Maybe it&#8217;s a possible security risk&#8230; ha, look at me worrying about security risks in a CPU that so far has to ability to run an operating system through lack of interrupts!). I&#8217;m also quite sure (thanks to shachaf on IRC) that my definitions for my <code>push</code> and <code>pop</code> instructions are wrong, there needs to be some addition to the stack pointer&#8217;s value before referencing it. I may also add a frame pointer to make life easier when working with function calls.</p>

<p>I may also add instructions to save a range of registers to the stack and load them back in, like ARM has (though I have no idea how to implement that just yet)</p>

<p>Lastly, there were some common operations, and some just plain cool ones I wanted to have available:</p>

<table>
<col />
<col />
<thead>
<tr>
    <th>Instruction</th>
    <th>Description</th>
</tr>
</thead>
<tbody>
<tr>
    <td>ctz</td>
    <td>Count trailing zeros</td>
</tr>
<tr>
    <td>ctlz</td>
    <td>Count leading zeros</td>
</tr>
<tr>
    <td>popcnt{,32,16,8}{a}</td>
    <td>Bit population count</td>
</tr>
<tr>
    <td>rpow2</td>
    <td>Round to next power of two</td>
</tr>
<tr>
    <td>extract</td>
    <td>Extract a range of bits res = op1[m..n] <code>shift</code> o. This might get removed, and made one of the instruction argument formats.</td>
</tr>
<tr>
    <td> </td>
    <td> </td>
</tr>
<tr>
    <td>mor</td>
    <td>See pages 11 and 12 (physical 16 and 17) of</td>
</tr>
<tr>
    <td>mxor</td>
    <td>https://docs.google.com/viewer?url=http://www-cs-faculty.stanford.edu/~uno/fasc1.ps.gz</td>
</tr>
</tbody>
</table>

<p>Many of these instructions are trivial to implement in hardware, but can take many many cycles to implement in software without proper support. I&#8217;m open to adding more of these if anyone can come up with some instructions they wish they had in their CPU of choice.</p>

<p>The last thing I wanted to talk about before finishing off this first post was my ideas on what I would do about registers. I mentioned earlier that I likes the SPARC idea of having a constant zero register. After I came up with the idea of the <code>extract</code> instruction, realised that having a register of all 1 bits would also be useful for creating masks. Having this means you could do things like complement all the bits in a certain range like so:</p>

<p><pre><code>xor r4, r4, r1[7:10]; # Use the constant 1's register to form a mask
</code></pre></p>

<p>I think this will turn out to be extremely useful in many situations.</p>

<p>So far this is what I&#8217;ve come up with as a tentative plan for registers:</p>

<table>
<col />
<col />
<thead>
<tr>
    <th>Register (alt name)</th>
    <th> </th>
</tr>
</thead>
<tbody>
<tr>
    <td>r0</td>
    <td>Constant zero register</td>
</tr>
<tr>
    <td>r1</td>
    <td>Constant <code>0xFFFFFFFFFFFFFFFF</code></td>
</tr>
<tr>
    <td>r2-r60</td>
    <td>General purpose (Maybe make r60 the frame pointer?)</td>
</tr>
<tr>
    <td>r61 (sp)</td>
    <td>Stack pointer</td>
</tr>
<tr>
    <td>r62 (ra)</td>
    <td>Return address</td>
</tr>
<tr>
    <td>r63 (ip)</td>
    <td>Instruction pointer</td>
</tr>
</tbody>
</table>

<p>I have some ideas about what the calling convention for this architecture should be, but that will have to wait for a later post.</p>

<p>In the coming weeks and months I hope flesh out the details and design of this architecture, and hopefully you&#8217;ll find it fun to follow along. I plan to put everything up on github eventually, but I want something more concrete first. My next post will go into more detail about the instruction formats I&#8217;ve come up with, as well as my first adventure into Kansas Lava and creating a moderately complex adder/subtracter circuit. Until next time, happy hacking!</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=327</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>OpenCL From Haskell &#8211; Hello World!</title>
		<link>http://random.axman6.com/blog/?p=310</link>
		<comments>http://random.axman6.com/blog/?p=310#comments</comments>
		<pubDate>Sat, 17 Dec 2011 07:21:57 +0000</pubDate>
		<dc:creator>axman6</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=310</guid>
		<description><![CDATA[It&#8217;s been a very long time since I&#8217;ve even looked at this blog, so I thought I should do something about that. For the past two days, I&#8217;ve been working on making the OpenCLWrappers nee OpenCLRaw package more usable, while fixing some bugs while I&#8217;m at it.

The main change I wanted to make was to [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a very long time since I&#8217;ve even looked at this blog, so I thought I should do something about that. For the past two days, I&#8217;ve been working on making the OpenCLWrappers nee OpenCLRaw package more usable, while fixing some bugs while I&#8217;m at it.</p>

<p>The main change I wanted to make was to move from everything returning <code>IO (Either ErrorCode a)</code> or <code>IO (Maybe ErrorCode)</code> to a more useable OpenCL monad. The obvious way to do this is to use ErrorT:</p>

<p><pre><span class='hs-varop'>&gt;</span> <span class='hs-keyword'>type</span> <span class='hs-conid'>OpenCL</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ErrorT</span> <span class='hs-conid'>ErrorCode</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
</pre></p>

<p>(Be sure to comment out the previous line if you decide to use this is a literate haskell file.)</p>

<p>This involved first converting all the <code>IO (Maybe ErrorCode)</code> functions to <code>IO (Either ErrorCode ())</code> first, and then implementing the OpenCL monad wrapper on top of that. This has resulted in a new set of modules under System.OpenCL.Monad.</p>

<p>To demonstrate how to make use of this initial work, I&#8217;ll use a slightly modified version of the <a href="http://developer.download.nvidia.com/OpenCL/NVIDIA_OpenCL_JumpStart_Guide.pdf" >canonical CUDA/OpenCL example</a> which takes two vectors of floats, an adds them. My slight modification is to make the kernel compute the hypotenuse between the two vectors. First let&#8217;s start with the OpenCL kernel, which should make more clear what we&#8217;re trying to do:</p>

<p><code>
<pre>
__kernel void vectorHypot(
    __global const float * a,
    __global const float * b,
    __global       float * c)
{
    int nIndex = get_global_id(0);
    c[nIndex] = sqrt(a[nIndex] * a[nIndex] + b[nIndex] * b[nIndex]);
}
</pre>
</code></p>

<p>Next comes the Haskell code. To make use of this code, you&#8217;ll need my latest version of <a href="https://github.com/axman6/OpenCLWrappers" >OpenCLWrappers from github</a>.</p>

<p>We start, as with any decent literate haskell document, with various imports to break the flow of the document (note to self, investigate using anansi in the future to see if it makes this easier).</p>

<p><pre><span class='hs-varop'>&gt;</span> <span class='hs-comment'>{-# LANGUAGE BangPatterns #-}</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>
</pre>
<pre><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'>OpenCL</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'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>OpenCL</span><span class='hs-varop'>.</span><span class='hs-conid'>Wrappers</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</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'>Random</span> <span class='hs-layout'>(</span><span class='hs-varid'>randoms</span><span class='hs-layout'>,</span> <span class='hs-varid'>mkStdGen</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Marshal</span><span class='hs-varop'>.</span><span class='hs-conid'>Array</span> <span class='hs-layout'>(</span><span class='hs-varid'>newArray</span><span class='hs-layout'>,</span> <span class='hs-varid'>peekArray</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Marshal</span><span class='hs-varop'>.</span><span class='hs-conid'>Alloc</span> <span class='hs-layout'>(</span><span class='hs-varid'>free</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span> <span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>Ptr</span> <span class='hs-layout'>(</span><span class='hs-varid'>castPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>nullPtr</span><span class='hs-layout'>,</span> <span class='hs-conid'>Ptr</span><span class='hs-layout'>)</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-layout'>(</span><span class='hs-varid'>forM</span><span class='hs-layout'>,</span> <span class='hs-varid'>forM_</span><span class='hs-layout'>)</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'>Bits</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varop'>.|.</span><span class='hs-layout'>)</span><span class='hs-layout'>)</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'>Time</span> <span class='hs-layout'>(</span><span class='hs-varid'>getCurrentTime</span><span class='hs-layout'>,</span> <span class='hs-varid'>diffUTCTime</span><span class='hs-layout'>)</span>
</pre></p>

<p>Next, we have a function to time execution times. I&#8217;m pretty sure it doesn&#8217;t work, so I&#8217;d love some suggestions for a better way to do this!</p>

<p><pre><span class='hs-varop'>&gt;</span> <span class='hs-definition'>time</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
<span class='hs-varop'>&gt;</span> <span class='hs-definition'>time</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varop'>!</span><span class='hs-varid'>before</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>getCurrentTime</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varop'>!</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>x</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varop'>!</span><span class='hs-varid'>after</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>getCurrentTime</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>print</span> <span class='hs-varop'>$</span> <span class='hs-varid'>diffUTCTime</span> <span class='hs-varid'>after</span> <span class='hs-varid'>before</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>return</span> <span class='hs-varid'>a</span>
</pre>
And finally on to the guts of the program.We start by reading in the source for the file. Then we create two lists of <code>len</code>&#8216; random Float values. I&#8217;m sure there are better ways to do this too, but I was after a quick (ha!) and dirty result.</p>

<p>The lists are then written to arrays, which are cast to pointers of () (equivalent to void *), so that it matches the types of required by <code>clCreateBuffer</code> later. Then we run the computation (via runHypot), the arrays are read and freed, and we check to see whether the results differ by much, compared to what we expect.</p>

<p><pre><span class='hs-varop'>&gt;</span> <span class='hs-definition'>len</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>2</span><span class='hs-varop'>^</span><span class='hs-num'>22</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span>
</pre>
<pre><span class='hs-varop'>&gt;</span> <span class='hs-definition'>main</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>str</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>readFile</span> <span class='hs-str'>"kernel.cl"</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>let</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>take</span> <span class='hs-varid'>len</span> <span class='hs-varop'>$</span> <span class='hs-varid'>randoms</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkStdGen</span> <span class='hs-num'>1</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Float</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>take</span> <span class='hs-varid'>len</span> <span class='hs-varop'>$</span> <span class='hs-varid'>randoms</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkStdGen</span> <span class='hs-num'>2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>Float</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pa'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newArray</span> <span class='hs-varid'>a</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pb'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newArray</span> <span class='hs-varid'>b</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pc'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newArray</span> <span class='hs-layout'>(</span><span class='hs-varid'>replicate</span> <span class='hs-varid'>len</span> <span class='hs-layout'>(</span><span class='hs-num'>0.0</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Float</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>psize'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>newArray</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>len</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>let</span> <span class='hs-varid'>pa</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>castPtr</span> <span class='hs-varid'>pa'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>()</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>pb</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>castPtr</span> <span class='hs-varid'>pb'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>()</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>pc</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>castPtr</span> <span class='hs-varid'>pc'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>()</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>psize</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>castPtr</span> <span class='hs-varid'>psize'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>()</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>time</span> <span class='hs-varop'>$</span> <span class='hs-varid'>runHypot</span> <span class='hs-varid'>str</span> <span class='hs-varid'>pa</span> <span class='hs-varid'>pb</span> <span class='hs-varid'>pc</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>cres</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>peekArray</span> <span class='hs-varid'>len</span> <span class='hs-varid'>pc'</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>free</span> <span class='hs-varid'>pa'</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>free</span> <span class='hs-varid'>pb'</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>free</span> <span class='hs-varid'>pc'</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>time</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span>
<span class='hs-varop'>&gt;</span>          <span class='hs-varop'>$</span> <span class='hs-varid'>take</span> <span class='hs-num'>100</span>
<span class='hs-varop'>&gt;</span>          <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>a</span><span class='hs-comment'>-</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>          <span class='hs-varop'>$</span> <span class='hs-varid'>dropWhile</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>abs</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-comment'>-</span><span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varop'>&lt;</span> <span class='hs-num'>10e-7</span><span class='hs-layout'>)</span>
<span class='hs-varop'>&gt;</span>          <span class='hs-varop'>$</span> <span class='hs-varid'>zipWith3</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>a</span> <span class='hs-varid'>b</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>sqrt</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-varop'><em></span><span class='hs-varid'>a</span> <span class='hs-varop'>+</span> <span class='hs-varid'>b</span><span class='hs-varop'></em></span><span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span> <span class='hs-varid'>cres</span>
</pre></p>

<p>Now we get to the uh&#8230; fun part. It turns out that OpenCL is amazingly tedious for such a simple task. The process of running a kernel is as follows:</p>

<ol>
<li>Find out about the platforms available</li>
    <li>Find out about all the devices you have access to. In my case, on my MacBook Pro I have access to one CPU, and one GPU. This gets printed on the following line.
    </li>
    <li>Select a device to run the computation on. I chose the GPU, mainly because choosing the CPU didn&#8217;t work for some reason. I may investigate this in the future</li>
    <li>Create an OpenCL context, which is used for all sorts of stuff&#8230;</li>
    <li>Create a command queue for the device. Each action you wish to perform on the device will be queued here, which including moving data to the device&#8217;s memory, running the kernels themselves, and moving data back to the host&#8217;s memory</li>
    <li>Next the program is created from the course passed in (originally from kernel.cl remember?)</li>
    <li>Next we compile the program. You can see I&#8217;ve had to jump through some hoops to make this work. I technically could have just run <code>clBuildProgram</code>, but the way I&#8217;ve done it allows me to get some info about what went wrong with the compilation. Here I print out the compile/error log returned from the compiler if something goes wrong.</li>
    <li>Buffers are created, which will have the contents of the host pointers we allocated and passed as arguments copied into them. This step is what moved the data onto the device.</li>
    <li>Finally we get to running the kernel. You may be wondering why I&#8217;m using the magic number <code>maxWISize `div` 4</code> here&#8230; I&#8217;m using it because it worked. I was hoping that just setting the work item size to maxWISize would work, but for some reason it doesn. I might investigate this later&#8230;</li>
    <li>Now all that&#8217;s left is to read the data back from the device, and then free the memory used on the device also. Once this is done, the pointer pc should contain our results.</li>
</ol>

<p><pre><span class='hs-varop'>&gt;</span> <span class='hs-definition'>runHypot</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Ptr</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-layout'>(</span><span class='hs-conid'>Either</span> <span class='hs-conid'>ErrorCode</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span><br />
<span class='hs-varop'>&gt;</span> <span class='hs-definition'>runHypot</span> <span class='hs-varid'>str</span> <span class='hs-varid'>pa</span> <span class='hs-varid'>pb</span> <span class='hs-varid'>pc</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runOpenCL</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pids</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clGetPlatformIDs</span>                              <span class='hs-comment'>-- 1</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>dids</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>fmap</span> <span class='hs-varid'>concat</span> <span class='hs-varop'>$</span> <span class='hs-varid'>forM</span> <span class='hs-varid'>pids</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>pid</span> <span class='hs-keyglyph'>-&gt;</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>clGetDeviceIDs</span> <span class='hs-varid'>pid</span> <span class='hs-varid'>clDeviceTypeAll</span>                <span class='hs-comment'>-- 2</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>infos</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>forM</span> <span class='hs-varid'>dids</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>did</span> <span class='hs-keyglyph'>-&gt;</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-varid'>clGetDeviceInfo</span> <span class='hs-varid'>did</span> <span class='hs-varid'>clDeviceType</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varid'>infos</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>let</span> <span class='hs-varid'>devid</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>dids</span> <span class='hs-varop'>!!</span> <span class='hs-num'>1</span>                                 <span class='hs-comment'>-- 3</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>ctx</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clCreateContext</span> <span class='hs-conid'>[]</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>devid</span><span class='hs-keyglyph'>]</span> <span class='hs-conid'>Nothing</span> <span class='hs-varid'>nullPtr</span>     <span class='hs-comment'>-- 4</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>queue</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clCreateCommandQueue</span> <span class='hs-varid'>ctx</span> <span class='hs-layout'>(</span><span class='hs-varid'>dids</span> <span class='hs-varop'>!!</span> <span class='hs-num'>1</span><span class='hs-layout'>)</span> <span class='hs-conid'>[]</span>      <span class='hs-comment'>-- 5</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>prog</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clCreateProgramWithSource</span> <span class='hs-varid'>ctx</span> <span class='hs-varid'>str</span>             <span class='hs-comment'>-- 6</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>err</span> <span class='hs-keyglyph'>&lt;-</span>  <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>runOpenCL</span> <span class='hs-varop'>$</span> <span class='hs-varid'>clBuildProgram</span> <span class='hs-varid'>prog</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>devid</span><span class='hs-keyglyph'>]</span> <span class='hs-str'>""</span> <span class='hs-conid'>Nothing</span> <span class='hs-varid'>nullPtr</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>case</span> <span class='hs-varid'>err</span> <span class='hs-keyword'>of</span>                                           <span class='hs-comment'>-- ^ 7</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-conid'>Left</span> <span class='hs-varid'>err</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<span class='hs-varop'>&gt;</span>             <span class='hs-varid'>x</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clGetProgramBuildInfo</span> <span class='hs-varid'>prog</span> <span class='hs-varid'>devid</span> <span class='hs-varid'>clProgramBuildLog</span>
<span class='hs-varop'>&gt;</span>             <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varid'>x</span>
<span class='hs-varop'>&gt;</span>         <span class='hs-conid'>Right</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>x</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>kern</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clCreateKernel</span> <span class='hs-varid'>prog</span> <span class='hs-str'>"vectorHypot"</span>               <span class='hs-comment'>-- 8</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>let</span> <span class='hs-varid'>bytes</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>len</span> <span class='hs-varop'>*</span> <span class='hs-num'>4</span>                      <span class='hs-comment'>-- 9</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pad'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clCreateBuffer</span> <span class='hs-varid'>ctx</span> <span class='hs-layout'>(</span><span class='hs-varid'>clMemReadOnly</span> <span class='hs-varop'>.|.</span> <span class='hs-varid'>clMemCopyHostPtr</span><span class='hs-layout'>)</span>  <span class='hs-varid'>bytes</span> <span class='hs-varid'>pa</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pbd'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clCreateBuffer</span> <span class='hs-varid'>ctx</span> <span class='hs-layout'>(</span><span class='hs-varid'>clMemReadOnly</span> <span class='hs-varop'>.|.</span> <span class='hs-varid'>clMemCopyHostPtr</span><span class='hs-layout'>)</span>  <span class='hs-varid'>bytes</span> <span class='hs-varid'>pb</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pcd'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clCreateBuffer</span> <span class='hs-varid'>ctx</span> <span class='hs-varid'>clMemWriteOnly</span> <span class='hs-varid'>bytes</span> <span class='hs-varid'>nullPtr</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pad</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>newArray</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>pad'</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pbd</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>newArray</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>pbd'</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>pcd</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>newArray</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>pcd'</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>clSetKernelArg</span> <span class='hs-varid'>kern</span> <span class='hs-num'>0</span> <span class='hs-num'>8</span> <span class='hs-varop'>$</span> <span class='hs-varid'>castPtr</span> <span class='hs-varid'>pad</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>clSetKernelArg</span> <span class='hs-varid'>kern</span> <span class='hs-num'>1</span> <span class='hs-num'>8</span> <span class='hs-varop'>$</span> <span class='hs-varid'>castPtr</span> <span class='hs-varid'>pbd</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>clSetKernelArg</span> <span class='hs-varid'>kern</span> <span class='hs-num'>2</span> <span class='hs-num'>8</span> <span class='hs-varop'>$</span> <span class='hs-varid'>castPtr</span> <span class='hs-varid'>pcd</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-layout'>(</span><span class='hs-conid'>DeviceInfoRetvalCLsizeiList</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span><span class='hs-conop'>:</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span>
<span class='hs-varop'>&gt;</span>           <span class='hs-varid'>clGetDeviceInfo</span> <span class='hs-varid'>devid</span> <span class='hs-varid'>clDeviceMaxWorkItemSizes</span>  <span class='hs-comment'>-- ^ 10</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-keyword'>let</span> <span class='hs-varid'>maxWISize</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>n</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>print</span> <span class='hs-varid'>maxWISize</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>eventRun</span> <span class='hs-keyglyph'>&lt;-</span>
<span class='hs-varop'>&gt;</span>       <span class='hs-varid'>clEnqueueNDRangeKernel</span> <span class='hs-varid'>queue</span> <span class='hs-varid'>kern</span>                   <span class='hs-comment'>-- 11</span>
<span class='hs-varop'>&gt;</span>                              <span class='hs-keyglyph'>[</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>len</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>                              <span class='hs-keyglyph'>[</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varid'>maxWISize</span> <span class='hs-varop'><code>div</code></span> <span class='hs-num'>4</span><span class='hs-keyglyph'>]</span> <span class='hs-conid'>[]</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>eventRead</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>clEnqueueReadBuffer</span> <span class='hs-varid'>pcd'</span> <span class='hs-conid'>True</span> <span class='hs-num'>0</span> <span class='hs-varid'>bytes</span>    <span class='hs-comment'>-- 12</span>
<span class='hs-varop'>&gt;</span>                                      <span class='hs-varid'>pc</span> <span class='hs-varid'>queue</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>eventRun</span><span class='hs-keyglyph'>]</span>
<span class='hs-varop'>&gt;</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>clEnqueueWaitForEvents</span> <span class='hs-varid'>queue</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>eventRun</span><span class='hs-layout'>,</span> <span class='hs-varid'>eventRead</span><span class='hs-keyglyph'>]</span>    <span class='hs-comment'>-- 13</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>clReleaseMemObject</span> <span class='hs-varid'>pad'</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>clReleaseMemObject</span> <span class='hs-varid'>pbd'</span>
<span class='hs-varop'>&gt;</span>     <span class='hs-varid'>clReleaseMemObject</span> <span class='hs-varid'>pcd'</span>
</pre></p>

<p>To compile, make sure you call ghc with -lopencl or -framework OpenCL on OS X: ghc -framework OpenCL main.lhs</p>

<p>As you can see, this is a hell of a lot of work to go through for such a simple task, and this is why I hope to make a higher level set of wrappers in the nearish future. I would love to be able to do everything using either Vectors or Repa arrays (the latter would be more ideal). It would also be nice to create a DSL for creating OpenCL kernels, but that&#8217;s a long way away at the moment.</p>

<p>I think I&#8217;ll focus first on making a cleaner interface to things like attaining a context, and allocating data.</p>

<p>Anyway, that&#8217;s it for now, let me know if you have any questions, or is anything doesn&#8217;t make sense.</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=310</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New primitive functions for the Haskell Array library</title>
		<link>http://random.axman6.com/blog/?p=285</link>
		<comments>http://random.axman6.com/blog/?p=285#comments</comments>
		<pubDate>Sat, 22 Jan 2011 14:52:14 +0000</pubDate>
		<dc:creator>axman6</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=285</guid>
		<description><![CDATA[In response to a recent post highlighting some performance problems with arrays in haskell I decided that there are some fairly primitive functions missing in the current array library. My attempt at fixing these issues is now on hackage in the array-utils package. My hope is that some or all of these functions will be [...]]]></description>
			<content:encoded><![CDATA[<p>In response to <a href="http://www.lix.polytechnique.fr/~kaustuv/expo/incr_uarray/">a recent post highlighting some performance problems with arrays in haskell</a> I decided that there are some fairly primitive functions missing in the current array library. My attempt at fixing these issues is now on hackage in the <a href="http://hackage.haskell.org/package/array-utils">array-utils</a> package. My hope is that some or all of these functions will be added to the <a href="http://hackage.haskell.org/package/array">array</a> package in GHC 7.2.</p>

<p>The functions I have implemented basically try to remove as much bounds checking as possible, so the implementation of these functions all use the unsafeRead, unsafeWrite and unsafeIndex functions to help avoid extra overhead. Some of the functions that are included are:</p>

<p style="padding-left: 30px;"><code>updateElems :: (MArray a e m, Ix i) =&gt; (e -&gt; e) -&gt; a i e -&gt; m ()</code></p>

<p style="padding-left: 60px;">Which updates every element in the array with the given function.</p>

<p style="padding-left: 30px;"><code>updateElemsM :: (MArray a e m, Ix i) =&gt; (e -&gt; m e) -&gt; a i e -&gt; m ()</code></p>

<p style="padding-left: 60px;">the monadic version</p>

<p style="padding-left: 30px;"><code>updateElemsIx :: (MArray a e m, Ix i) =&gt; (i -&gt; e -&gt; e) -&gt; a i e -&gt; m ()</code></p>

<p style="padding-left: 60px;">also provides the index to the update function. There&#8217;s also a monadic version of this.</p>

<p style="padding-left: 30px;"><code>updateWithin :: (MArray a e m, Ix i) =&gt; (e -&gt; e)  -&gt; (i,i) -&gt; a i e -&gt; m ()</code></p>

<p style="padding-left: 60px;">Which updates every element in the line/rectangle/prism defined by the start and end indexes.</p>

<p style="padding-left: 30px;"><code>updateOn :: (MArray a e m, Ix i) =&gt; (e -&gt; e) -&gt; [i] -&gt; a i e -&gt; m ()</code></p>

<p style="padding-left: 60px;">Which updates the given indices.</p>

<p style="padding-left: 30px;"><code>updateSlice :: (MArray a e m, Ix i) =&gt; (e -&gt; e) -&gt; (i,i) -&gt; a i e -&gt; m ()</code></p>

<p style="padding-left: 60px;">Which updates every element from the start index until the end index, so every element in the flat array from start to end.</p>

<p style="padding-left: 60px;"><strong>Update:</strong> The difference between updateWithin and updateSlice is that if you have a 2D array with indices from (1,1) to (10,10) and you say updateSlice (+10) ((2,5),(4,2)) arr, then it will add 10 to all elements whose index is between<strong> <code>index ((1,1),(10,10)) (2,5)</code></strong> which is 14 and <code><strong>index ((1,1),(10,10)) (4,2)</strong></code> which is 35. So it will update elements 5 to 10 on row 2, 1 to 10 on row 3, and 1 to 2 on row 4. If you used updateWithin here, it wouldn&#8217;t update anything, because range ((2,5),(4,2)) returns an empty list. I might do another post with images to help clear this up.</p>

<p>All functions in the module use Int based indexing and unsafe functions internally to hopefully speed up the code that&#8217;s generated.</p>

<p>I&#8217;m yet to benchmark these functions and see whether they would make any difference to the results of the above article (I doubt they&#8217;d be any faster than the Ptr versions). Whether they are faster or not, they should hopefully save a fair amount of code for a lot people that&#8217;s easy to get wrong. When I do benchmark these, I&#8217;ll add the results to this blog.</p>

<p>Speaking of getting it wrong, while I am fairly confident, I haven&#8217;t fully tested these functions yet, so if you feel they would be useful to you, and you run into strange results, I would love to know about it! I&#8217;m hoping to figure out how to get quickcheck to run some tests, and hopefully I&#8217;ll have that done next weekend.</p>

<p>If you can think of any more functions you think should be in the array package, please let me know, and I&#8217;ll see if I can add them. All the code is available on <a href="https://github.com/axman6/array-utils">GitHub</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=285</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Co-routines in Haskell</title>
		<link>http://random.axman6.com/blog/?p=231</link>
		<comments>http://random.axman6.com/blog/?p=231#comments</comments>
		<pubDate>Wed, 21 Jul 2010 13:49:36 +0000</pubDate>
		<dc:creator>blackh</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=231</guid>
		<description><![CDATA[It is easy to implement co-routines in Haskell&#8230; but only if you know how.  No fewer than three people asked me to blog about it, so here&#8217;s a quick guide to rolling your own co-routines.  To understand this blog, you will need to have a basic understanding of monad transformers.

There are co-routine packages [...]]]></description>
			<content:encoded><![CDATA[<p>It is easy to implement co-routines in Haskell&#8230; but only if you know how.  No fewer than three people asked me to blog about it, so here&#8217;s a quick guide to rolling your own co-routines.  To understand this blog, you will need to have a basic understanding of monad transformers.</p>

<p>There are co-routine packages on Hackage, but I have not had much luck with them. The point here, really, is to show you how it all works.</p>

<p><strong>What&#8217;s a co-routine?</strong></p>

<p>A co-routine (called a &#8216;generator&#8217; in Python) is where you create two interleaved flows of control on a single thread.  Unlike threads, co-routines switch co-operatively using a &#8216;yield&#8217; operation.  (This is quite a good trick in GUI programming for implementing complex workflow that spans multiple GUI events, since most GUI libraries require everything to be on one thread.)</p>

<p>The example I&#8217;m presenting here works in this way:  A caller executes a CoroutineT monad transformer, which adds the &#8216;yield&#8217; operation to the underlying monad (which can be anything).  From the caller&#8217;s point of view, the &#8216;yield&#8217; looks like the monad has returned, but with a continuation.  In the callee, &#8216;yield&#8217; appears to block until the caller executes the continuation.  In addition, we add the ability to pass a value in both directions.</p>

<p>So we&#8217;ve inverted the flow of control in the callee.  Continuation passing style (CPS) can also do this, but co-routines are better than CPS because 1. it&#8217;s a bit neater, and 2. it allows for recursion.</p>

<p>One application of co-routines is to separate I/O from logic.  By way of example I am going to implement an <em>expert system for identifying fruit</em>.  I try not to use contrived examples, and as you can see, this time I have completely failed.</p>

<p>In this example, the CoroutineT sits on top of the identity monad, so it&#8217;s pure, but the approach works just the same on top of IO or anything else.  This example is not deeply nested, but this approach happily supports any level of recursion or nesting.</p>

<p>So here&#8217;s our expert system logic. We&#8217;ll define <b>CoroutineT</b> shortly.  You can read &#8216;yield&#8217; as &#8216;askUser&#8217;:</p>

<p><pre><font color="Green"><u>type</u></font> Question <font color="Red">=</font> String
<font color="Green"><u>data</u></font> Answer <font color="Red">=</font> Y <font color="Red">|</font> N <font color="Green"><u>deriving</u></font> Eq
</pre>
<pre><font color="Green"><u>type</u></font> Expert a <font color="Red">=</font> CoroutineT Answer Question Identity a
</pre>
<pre><font color="Green"><u>data</u></font> Fruit
    <font color="Red">=</font> Apple
    <font color="Red">|</font> Kiwifruit
    <font color="Red">|</font> Banana
    <font color="Red">|</font> Orange
    <font color="Red">|</font> Lemon
    <font color="Green"><u>deriving</u></font> Show
</pre>
<pre><font color="Blue">identifyFruit</font> <font color="Red">::</font> Expert Fruit
<font color="Blue">identifyFruit</font> <font color="Red">=</font> <font color="Green"><u>do</u></font>
    yellow <font color="Red">&lt;-</font> yield <font color="Magenta">"Is it yellow?"</font>
    <font color="Green"><u>if</u></font> yellow <font color="Cyan">==</font> Y <font color="Green"><u>then</u></font> <font color="Green"><u>do</u></font>
        long <font color="Red">&lt;-</font> yield <font color="Magenta">"Is it long?"</font>
        <font color="Green"><u>if</u></font> long <font color="Cyan">==</font> Y <font color="Green"><u>then</u></font>
            return Banana
          <font color="Green"><u>else</u></font>
            return Lemon
      <font color="Green"><u>else</u></font> <font color="Green"><u>do</u></font>
        orange <font color="Red">&lt;-</font> yield <font color="Magenta">"Is it orange?"</font>
        <font color="Green"><u>if</u></font> orange <font color="Cyan">==</font> Y <font color="Green"><u>then</u></font>
           return Orange
         <font color="Green"><u>else</u></font> <font color="Green"><u>do</u></font>
           fuzzy <font color="Red">&lt;-</font> yield <font color="Magenta">"Is it fuzzy?"</font>
           <font color="Green"><u>if</u></font> fuzzy <font color="Cyan">==</font> Y <font color="Green"><u>then</u></font>
               return Kiwifruit
             <font color="Green"><u>else</u></font>
               return Apple
</pre></p>

<p>Our &#8216;Expert&#8217; type above&#8230;</p>

<p><pre><font color="Green"><u>type</u></font> Expert a <font color="Red">=</font> CoroutineT Answer Question Identity a
</pre></p>

<p>&#8230;specifies the type we are sending into our co-routine (Answer) and the type we are getting out of it (Question) as viewed from the caller.</p>

<p>Now we just need a main program to drive it.  Because the I/O is separated out, we can later replace this with a nice touch-screen GUI for the seriously fruit-impaired.</p>

<p><pre><font color="Blue">main</font> <font color="Red">::</font> IO ()
<font color="Blue">main</font> <font color="Red">=</font> <font color="Green"><u>do</u></font>
    putStrLn <font color="Cyan">$</font> <font color="Magenta">"Expert system for identifying fruit"</font>
    run identifyFruit
  <font color="Green"><u>where</u></font>
    run <font color="Red">::</font> Expert Fruit <font color="Red">-&gt;</font> IO ()
    run exp <font color="Red">=</font> handle <font color="Cyan">$</font> runIdentity <font color="Cyan">$</font> runCoroutineT exp
</pre>
<pre>    handle <font color="Cyan">(</font>Yield q cont<font color="Cyan">)</font> <font color="Red">=</font> <font color="Green"><u>do</u></font>
        putStrLn q
        l <font color="Red">&lt;-</font> getLine
        <font color="Green"><u>case</u></font> map toLower l <font color="Green"><u>of</u></font>
            <font color="Magenta">"y"</font>   <font color="Red">-&gt;</font> run <font color="Cyan">$</font> cont Y
            <font color="Magenta">"yes"</font> <font color="Red">-&gt;</font> run <font color="Cyan">$</font> cont Y
            <font color="Magenta">"n"</font>   <font color="Red">-&gt;</font> run <font color="Cyan">$</font> cont N
            <font color="Magenta">"no"</font>  <font color="Red">-&gt;</font> run <font color="Cyan">$</font> cont N
            <font color="Green"><u>_</u></font>   <font color="Red">-&gt;</font> putStrLn <font color="Magenta">"Please answer 'yes' or 'no'"</font> <font color="Cyan">&gt;&gt;</font> handle <font color="Cyan">(</font>Yield q cont<font color="Cyan">)</font>
</pre>
<pre>    handle <font color="Cyan">(</font>Result fruit<font color="Cyan">)</font> <font color="Red">=</font> <font color="Green"><u>do</u></font>
        putStrLn <font color="Cyan">$</font> <font color="Magenta">"The fruit you have is: "</font><font color="Cyan">++</font>show fruit
</pre></p>

<p>When we run our co-routine, it returns with one of these two events:</p>

<ul>
    <li><b>Yield</b>, which happens when yield is executed.  It gives us the output value (Question) and the continuation, which when passed the input value (Answer) gives us the same &#8216;Expert&#8217; type we started with.</li>
        <li><b>Result</b>, which happens when the co-routine has finished executing.
</ul>

<p><b>So how does CoroutineT work?</b></p>

<p>We&#8217;ll start with the types:</p>

<p><pre><font color="Green"><u>data</u></font> Result i o m a <font color="Red">=</font> Yield o <font color="Cyan">(</font>i <font color="Red">-&gt;</font> CoroutineT i o m a<font color="Cyan">)</font> <font color="Red">|</font> Result a
</pre>
<pre><font color="Blue"><i>-- | Co-routine monad transformer</i></font>
<font color="Blue"><i>--</i></font>
<font color="Blue"><i>--   * i = input value returned by yield</i></font>
<font color="Blue"><i>--</i></font>
<font color="Blue"><i>--   * o = output value, passed to yield</i></font>
<font color="Blue"><i>--</i></font>
<font color="Blue"><i>--   * m = next monad in stack</i></font>
<font color="Blue"><i>--</i></font>
<font color="Blue"><i>--   * a = monad return value</i></font>
<font color="Green"><u>data</u></font> CoroutineT i o m a <font color="Red">=</font> CoroutineT <font color="Cyan">{</font>
        runCoroutineT <font color="Red">::</font> m <font color="Cyan">(</font>Result i o m a<font color="Cyan">)</font>
    <font color="Cyan">}</font>
</pre></p>

<p>Hopefully that&#8217;s pretty straightforward.  &#8216;yield&#8217; is defined like this:</p>

<p><pre><font color="Blue"><i>-- | Suspend processing, returning a @o@ value and a continuation to the caller</i></font>
<font color="Blue">yield</font> <font color="Red">::</font> Monad m <font color="Red">=&gt;</font> o <font color="Red">-&gt;</font> CoroutineT i o m i
<font color="Blue">yield</font> o <font color="Red">=</font> CoroutineT <font color="Cyan">$</font> return <font color="Cyan">$</font> Yield o <font color="Cyan">(</font><font color="Red">\</font>i <font color="Red">-&gt;</font> CoroutineT <font color="Cyan">$</font> return <font color="Cyan">$</font> Result i<font color="Cyan">)</font>
</pre></p>

<p>The key point here is that the continuation does nothing except return the value, which is what we want it to do when we run a monad that contains only a yield.</p>

<p>Most of the magic is in the definition of &gt;&gt;=, thus:</p>

<p><pre><font color="Green"><u>instance</u></font> Monad m <font color="Red">=&gt;</font> Monad <font color="Cyan">(</font>CoroutineT i o m<font color="Cyan">)</font> <font color="Green"><u>where</u></font>
    return a <font color="Red">=</font> CoroutineT <font color="Cyan">$</font> return <font color="Cyan">$</font> Result a
    f <font color="Cyan">&gt;&gt;=</font> g <font color="Red">=</font> CoroutineT <font color="Cyan">$</font> <font color="Green"><u>do</u></font>
        res1 <font color="Red">&lt;-</font> runCoroutineT f
        <font color="Green"><u>case</u></font> res1 <font color="Green"><u>of</u></font>
            Yield o c <font color="Red">-&gt;</font> return <font color="Cyan">$</font> Yield o <font color="Cyan">(</font><font color="Red">\</font>i <font color="Red">-&gt;</font> c i <font color="Cyan">&gt;&gt;=</font> g<font color="Cyan">)</font>
            Result a  <font color="Red">-&gt;</font> runCoroutineT <font color="Cyan">(</font>g a<font color="Cyan">)</font>
    <font color="Blue"><i>-- Pass fail to next monad in the stack</i></font>
    fail err <font color="Red">=</font> CoroutineT <font color="Cyan">$</font> fail err
</pre></p>

<p>A typical monad would normally execute <b>f</b> then pass its result to <b>g</b> and execute that, and this is in fact exactly what we do in the <b>Result</b> case. Ho hum.</p>

<p>But there&#8217;s no law that says you have to execute <b>g</b>.  This is Haskell so we can do whatever we like.  <b>g</b> is just a plain old closure representing the continuation.</p>

<p>So what we do in the <b>Yield</b> case is take the continuation that executing <b>f</b> gave us, and bind that to the continuation <b>g</b>, then bail out of the monad (in the same way ErrorT does when it gets an error), handing our constructed continuation to the caller.  So we end up with a closure that represents the entire execution state of the monad, and it doesn&#8217;t matter how deeply nested we are.  It just puts the continuation together in the right way as we unravel everything on our way back to the caller.</p>

<p>Here&#8217;s the code in downloadable form:</p>

<ul>
    <li><a href="/blackh/expert.hs">expert.hs</a></li>
        <li><a href="/blackh/Coroutine.hs">Coroutine.hs</a></li>
</ul>

<p>This code is released in the public domain.</p>

<p><i>Stephen Blackheath, Manawatu, New Zealand</i></p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=231</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>AusHac2010 Day 2 progress</title>
		<link>http://random.axman6.com/blog/?p=224</link>
		<comments>http://random.axman6.com/blog/?p=224#comments</comments>
		<pubDate>Sat, 17 Jul 2010 08:14:10 +0000</pubDate>
		<dc:creator>axman6</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=224</guid>
		<description><![CDATA[Day 2 of AusHac2010 is coming to an end, and we&#8217;ve made a lot of progress:

 • Bernie Pope has been making great progress with a new MPI binding for Haskell

 • Ben Lippmeier, Erik de Castro Lopo and Ben Sinclair have been busily hacking on DDC, with 13 commits today alone

 • Stephen Blackheath [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Day 2 of AusHac2010 is coming to an end, and we&#8217;ve made a lot of progress:</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Bernie Pope has been making great progress with a new MPI binding for Haskell</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Ben Lippmeier, Erik de Castro Lopo and Ben Sinclair have been busily hacking on DDC, with 13 commits today alone</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Stephen Blackheath has been working on some code using the Accelerate library that rasterises triangles for use in a commercial computer game.</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Hamish Mackenzie, Jens Petersen and Matthew Sellers have been working on better Yi integration for Leksah, working on using Yi&#8217;s current configuration file, and improving &#8220;launch experience&#8221;, focusing on eliminating the requirement of creating an initial workspace file.</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Lang Hames has been using his experience with LLVM from working at Apple as an intern to improve various low level problems in LLVM. His work should help resolve some of the problems the LLVM backend to GHC has, but should also be very beneficial to many other LLVM users. While doing this, he&#8217;s written a very nice tool that illustrates register liveness, with further work focusing on colouring the HTML output to show register pressure. The LLVM guys seem quite excited about this work, which is great.</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Mark Wotton and Sohum Banerjea have been trying to extend Hubris, the Haskell-Ruby bridge, to work with polymorphic functions. Their heads are quite sore from all the head banging. Raphael Speyer has been working on an install script to make installation much easier for users.. but only if you use Ubuntu so far.</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Ivan Miljenovic has been prematurely optimising his containers library, before finalising the API. This library is designed to let library writers leave the choice of which container data structure to output to the library consumer as well as making it easier to change which data structure you want to use in your code, with minimal code change. See his blog post for more details. **********</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Trevor McDonell has been working on the CUDA backend to Accelerate, adding support for efficient nested tuple types, and other bug fixes. Sean Lee has been helping out with testing of this code, along with Manuel Chakravarty.</div>

<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">With one more full day to go, I think we&#8217;ll be getting a lot of awesome work done tomorrowQ!</div>

<p>Day 2 of AusHac2010 is coming to an end, and we&#8217;ve made a lot of progress:</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Bernie Pope has been making great progress with a new MPI binding for Haskell</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Ben Lippmeier, Erik de Castro Lopo and Ben Sinclair have been busily hacking on DDC, with 13 commits today alone</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Stephen Blackheath has been working on some code using the Accelerate library that rasterises triangles for use in a commercial computer game.</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Hamish Mackenzie, Jens Petersen and Matthew Sellers have been working on better Yi integration for Leksah, working on using Yi&#8217;s current configuration file, and improving &#8220;launch experience&#8221;, focusing on eliminating the requirement of creating an initial workspace file.</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Lang Hames has been using his experience with LLVM from working at Apple as an intern to improve various low level problems in LLVM. His work should help resolve some of the problems the LLVM backend to GHC has, but should also be very beneficial to many other LLVM users. While doing this, he&#8217;s written a very nice tool that illustrates register liveness, with further work focusing on colouring the HTML output to show register pressure. The LLVM guys seem quite excited about this work, which is great.</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Mark Wotton and Sohum Banerjea have been trying to extend Hubris, the Haskell-Ruby bridge, to work with polymorphic functions. Their heads are quite sore from all the head banging. Raphael Speyer has been working on an install script to make installation much easier for users.. but only if you use Ubuntu so far.</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Ivan Miljenovic has been prematurely optimising his containers library, before finalising the API. This library is designed to let library writers leave the choice of which container data structure to output to the library consumer as well as making it easier to change which data structure you want to use in your code, with minimal code change. See his <a href="http://ivanmiljenovic.wordpress.com/2010/07/14/data-oriented-hierarchies/">blog post</a> for more details.</p>

<p><span style="white-space: pre;"> </span>•<span style="white-space: pre;"> </span>Trevor McDonell has been working on the CUDA backend to Accelerate, adding support for efficient nested tuple types, and other bug fixes. Sean Lee has been helping out with testing of this code, along with Manuel Chakravarty.</p>

<p>With one more full day to go, I think we&#8217;ll be getting a lot of awesome work done tomorrow!</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=224</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AusHac2010 Day 1 progress</title>
		<link>http://random.axman6.com/blog/?p=219</link>
		<comments>http://random.axman6.com/blog/?p=219#comments</comments>
		<pubDate>Sat, 17 Jul 2010 04:23:42 +0000</pubDate>
		<dc:creator>axman6</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[OSS]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=219</guid>
		<description><![CDATA[So, the first half day of AusHac2010 was yesterday. We had about 12 people turn up, which isn&#8217;t too bad for a Friday.

Erik de Castro Lopo did a lot of work on Ben Lippmeier&#8217;s DDC compiler for his Disciple language.

There was some initial work on the Accelerate library for accelerated array computations in Haskell, using [...]]]></description>
			<content:encoded><![CDATA[<p>So, the first half day of AusHac2010 was yesterday. We had about 12 people turn up, which isn&#8217;t too bad for a Friday.</p>

<blockquote>Erik de Castro Lopo did a lot of work on Ben Lippmeier&#8217;s <a href="http://trac.haskell.org/ddc/" target="_blank">DDC compiler </a>for his Disciple language.</blockquote>

<blockquote>There was some initial work on the Accelerate library for accelerated array computations in Haskell, using various backends. Most of the current work is aiming at making the CUDA backend usable, after which more backends will likely be added, such as an LLVM backend, and possibly an OpenCL backend as well.</blockquote>

<p>Due to the restricted time yesterday, not all that much work was started, but day 2 (see my next post!) has been much more productive.</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=219</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chunked XML parsing is the latest thing, you know</title>
		<link>http://random.axman6.com/blog/?p=157</link>
		<comments>http://random.axman6.com/blog/?p=157#comments</comments>
		<pubDate>Fri, 14 May 2010 14:15:43 +0000</pubDate>
		<dc:creator>blackh</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[GHC]]></category>
		<category><![CDATA[hackage]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=157</guid>
		<description><![CDATA[Uhh, hello.  Welcome to my first blog post ever &#8211; and thanks Axman6 for letting me be a &#8220;guest blogger&#8221;.

It&#8217;s rather unfashionable on #haskell, but I like XML.  So, 18 months ago, I took over the hexpat package from Evan Martin.  It was going to be a small project &#8211; a simple XML parser binding [...]]]></description>
			<content:encoded><![CDATA[<p>Uhh, hello.  Welcome to my first blog post ever &#8211; and thanks Axman6 for letting me be a &#8220;guest blogger&#8221;.</p>

<p>It&#8217;s rather unfashionable on <strong>#haskell</strong>, but I like XML.  So, 18 months ago, I took over the <a href="http://hackage.haskell.org/package/hexpat"><em>hexpat</em></a> package from Evan Martin.  It was going to be a small project &#8211; a simple XML parser binding to <a href="http://expat.sourceforge.net/">Expat</a>.  The fastest Haskell XML parser alive.  Or so I thought.</p>

<p>It&#8217;s become a passion, a way of life.  It&#8217;s XML parsing in Haskell the way <em>I</em> think it should be done.  The best as well as the fastest.  (I like to think big.)</p>

<p>I&#8217;ve finally finished adding all the features that I and a number of <a href="http://hackage.haskell.org/package/hexpat">contributors</a> wanted, and I would now like to announce that <strong>hexpat is going beta</strong>.  I want to make this package really, really good, so please help by testing and critiquing.  I want to stabilize <em>hexpat</em>, but <em>hexpat-iteratee</em> will be unstable for a while yet.</p>

<p><strong>The future is chunky</strong></p>

<p>The cherry on top of the <em>hexpat</em> galaxy is the still experimental <a href="http://hackage.haskell.org/package/hexpat-iteratee"><em>hexpat-iteratee</em></a> based on Oleg Kiselyov&#8217;s <em>iteratee</em>, which is a bit of a hot ticket these days.  It provides lazy XML parsing without the practical issues and philosophical dodginess inherent in Haskell&#8217;s lazy I/O through functions like <em>hGetContents</em>.</p>

<p><em>hexpat-iteratee</em> allows for effectful XML processing done in a functional way, and the magic behind this is Yair Chuchem&#8217;s humbly named <em>List</em> package.  It is &#8220;merely&#8221; a generalization of lists, and I think it deserves to be a common piece of infrastructure.</p>

<p>The example project is a <strong>chunked XML-over-TCP movie database lookup server</strong>.  Every home should have one.  So, let&#8217;s start like all good blogs do, with imports:
<pre><span class="hs-comment">{-# LANGUAGE OverloadedStrings #-}</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Control</span><span class="hs-varop">.</span><span class="hs-conid">Concurrent</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Control</span><span class="hs-varop">.</span><span class="hs-conid">Exception</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-keyword">import</span> <span class="hs-conid">Control</span><span class="hs-varop">.</span><span class="hs-conid">Monad</span><span class="hs-varop">.</span><span class="hs-conid">IO</span><span class="hs-varop">.</span><span class="hs-conid">Class</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">.</span><span class="hs-conid">ListT</span>
<span class="hs-keyword">import</span> <span class="hs-keyword">qualified</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span> <span class="hs-keyword">as</span> <span class="hs-conid">B</span>
<span class="hs-keyword">import</span> <span class="hs-keyword">qualified</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span><span class="hs-varop">.</span><span class="hs-conid">Unsafe</span> <span class="hs-keyword">as</span> <span class="hs-conid">B</span> <span class="hs-layout">(</span><span class="hs-varid">unsafeUseAsCStringLen</span><span class="hs-layout">)</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Iteratee</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Iteratee</span><span class="hs-varop">.</span><span class="hs-conid">IO</span><span class="hs-varop">.</span><span class="hs-conid">Fd</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Iteratee</span><span class="hs-varop">.</span><span class="hs-conid">WrappedByteString</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">.</span><span class="hs-conid">Class</span> <span class="hs-keyword">as</span> <span class="hs-conid">List</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-keyword">import</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Text</span> <span class="hs-layout">(</span><span class="hs-conid">Text</span><span class="hs-layout">)</span>
<span class="hs-keyword">import</span> <span class="hs-keyword">qualified</span> <span class="hs-conid">Data</span><span class="hs-varop">.</span><span class="hs-conid">Text</span> <span class="hs-keyword">as</span> <span class="hs-conid">T</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Network</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-keyword">import</span> <span class="hs-conid">System</span><span class="hs-varop">.</span><span class="hs-conid">Posix</span><span class="hs-varop">.</span><span class="hs-conid">IO</span> <span class="hs-layout">(</span><span class="hs-varid">handleToFd</span><span class="hs-layout">,</span> <span class="hs-varid">fdWriteBuf</span><span class="hs-layout">,</span> <span class="hs-varid">closeFd</span><span class="hs-layout">)</span>
<span class="hs-keyword">import</span> <span class="hs-conid">System</span><span class="hs-varop">.</span><span class="hs-conid">Posix</span><span class="hs-varop">.</span><span class="hs-conid">Types</span> <span class="hs-layout">(</span><span class="hs-conid">Fd</span><span class="hs-layout">)</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Text</span><span class="hs-varop">.</span><span class="hs-conid">XML</span><span class="hs-varop">.</span><span class="hs-conid">Expat</span><span class="hs-varop">.</span><span class="hs-conid">Chunked</span>
<span class="hs-keyword">import</span> <span class="hs-keyword">qualified</span> <span class="hs-conid">Text</span><span class="hs-varop">.</span><span class="hs-conid">XML</span><span class="hs-varop">.</span><span class="hs-conid">Expat</span><span class="hs-varop">.</span><span class="hs-conid">Chunked</span> <span class="hs-keyword">as</span> <span class="hs-conid">Tree</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Text</span><span class="hs-varop">.</span><span class="hs-conid">XML</span><span class="hs-varop">.</span><span class="hs-conid">Expat</span><span class="hs-varop">.</span><span class="hs-conid">Format</span>
<span class="hs-keyword">import</span> <span class="hs-conid">Foreign</span><span class="hs-varop">.</span><span class="hs-conid">Ptr</span></pre>
The first thing we want to do is listen on a socket.  I could use handles, sockets, or file descriptors.  With handles, this  code does not work interactively.  Disabling the buffering does not seem  to work at all in GHC 6.10 or 6.12.  Sockets would be ideal, but to  save me writing an <em>iteratee</em> driver, I&#8217;m left with file  descriptors which unfortunately means this code only works on GHC 6.12  on a POSIX system.  <strong>fdPutStrBS</strong> is the only glue I need then &#8211; it  writes a ByteString to a Fd.   Here&#8217;s the code:
<pre><span class="hs-definition">main</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">IO</span> <span class="hs-conid">()</span>
<span class="hs-definition">main</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
    <span class="hs-keyword">let</span> <span class="hs-varid">port</span> <span class="hs-keyglyph">=</span> <span class="hs-num">6333</span>
    <span class="hs-varid">putStrLn</span> <span class="hs-varop">$</span> <span class="hs-str">"listening on port "</span><span class="hs-varop">++</span><span class="hs-varid">show</span> <span class="hs-varid">port</span>
    <span class="hs-varid">ls</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">listenOn</span> <span class="hs-varop">$</span> <span class="hs-conid">PortNumber</span> <span class="hs-varid">port</span>
    <span class="hs-varid">forever</span> <span class="hs-varop">$</span> <span class="hs-keyword">do</span>
        <span class="hs-layout">(</span><span class="hs-varid">h</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">&lt;-</span> <span class="hs-varid">accept</span> <span class="hs-varid">ls</span>
        <span class="hs-varid">forkIO</span> <span class="hs-varop">$</span> <span class="hs-varid">handleToFd</span> <span class="hs-varid">h</span> <span class="hs-varop">&gt;&gt;=</span> <span class="hs-keyglyph">\</span><span class="hs-varid">fd</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-keyword">do</span>
            <span class="hs-varid">iter</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">parse</span> <span class="hs-varid">defaultParserOptions</span> <span class="hs-layout">(</span><span class="hs-varid">session</span> <span class="hs-layout">(</span><span class="hs-varid">fdPutStrBS</span> <span class="hs-varid">fd</span><span class="hs-layout">)</span><span class="hs-layout">)</span>
            <span class="hs-varid">result</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">enumFd</span> <span class="hs-varid">fd</span> <span class="hs-varid">iter</span> <span class="hs-varop">&gt;&gt;=</span> <span class="hs-varid">run</span>
            <span class="hs-varid">print</span> <span class="hs-varid">result</span>
          <span class="hs-varop">&#96;finally&#96;</span>
            <span class="hs-varid">closeFd</span> <span class="hs-varid">fd</span></p>

<p><span class="hs-definition">fdPutStrBS</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Fd</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">IO</span> <span class="hs-conid">()</span>
<span class="hs-definition">fdPutStrBS</span> <span class="hs-varid">fd</span> <span class="hs-varid">bs</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-varid">unsafeUseAsCStringLen</span> <span class="hs-varid">bs</span> <span class="hs-varop">$</span> <span class="hs-keyglyph">\</span><span class="hs-layout">(</span><span class="hs-varid">buf</span><span class="hs-layout">,</span> <span class="hs-varid">len</span><span class="hs-layout">)</span> <span class="hs-keyglyph">-&gt;</span>
        <span class="hs-varid">writeFully</span> <span class="hs-layout">(</span><span class="hs-varid">castPtr</span> <span class="hs-varid">buf</span><span class="hs-layout">)</span> <span class="hs-layout">(</span><span class="hs-varid">fromIntegral</span> <span class="hs-varid">len</span><span class="hs-layout">)</span>
  <span class="hs-keyword">where</span>
    <span class="hs-varid">writeFully</span> <span class="hs-keyword">_</span> <span class="hs-varid">len</span> <span class="hs-keyglyph">|</span> <span class="hs-varid">len</span> <span class="hs-varop">==</span> <span class="hs-num">0</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">return</span> <span class="hs-conid">()</span>
    <span class="hs-varid">writeFully</span> <span class="hs-varid">buf</span> <span class="hs-varid">len</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
        <span class="hs-varid">written</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">fdWriteBuf</span> <span class="hs-varid">fd</span> <span class="hs-varid">buf</span> <span class="hs-varid">len</span>
        <span class="hs-keyword">if</span> <span class="hs-varid">written</span> <span class="hs-varop">&lt;</span> <span class="hs-num">0</span>
            <span class="hs-keyword">then</span> <span class="hs-varid">fail</span> <span class="hs-str">"write failed"</span>
            <span class="hs-keyword">else</span> <span class="hs-varid">writeFully</span> <span class="hs-layout">(</span><span class="hs-varid">buf</span> <span class="hs-varop">&#96;plusPtr&#96;</span> <span class="hs-varid">fromIntegral</span> <span class="hs-varid">written</span><span class="hs-layout">)</span> <span class="hs-layout">(</span><span class="hs-varid">len</span> <span class="hs-comment">-</span> <span class="hs-varid">written</span><span class="hs-layout">)</span></pre>
Once we&#8217;ve accepted the connection, we get <strong>parse</strong> (from <em>hexpat-iteratee</em>) to make us an iteratee.  The second argument, &#8220;session (fdPutStrBS fd)&#8221; is the handler for processing the document.  We then pass this iteratee to <em>iteratee</em>&#8217;s <strong>enumFd</strong>, whose job it is to pull the input data out of the Fd and feed it into the parser. <strong>parse</strong> is monadic in order that it can start the handler before it receives the first data block through the iteratee. This is necessary in case the handler wants to generate output before it gets any input, which we want to do here.</p>

<p>The handler is a co-routine.  When it runs out of input data, it gets suspended, and control returns to <strong>enumFd</strong>.
<pre><span class="hs-definition">session</span> <span class="hs-keyglyph">::</span> <span class="hs-layout">(</span><span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">IO</span> <span class="hs-conid">()</span><span class="hs-layout">)</span>  <span class="hs-comment">-- ^ Write output data to socket</span>
        <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">ListOf</span> <span class="hs-layout">(</span><span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span><span class="hs-layout">)</span>   <span class="hs-comment">-- ^ Input XML document</span>
        <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">XMLT</span> <span class="hs-conid">IO</span> <span class="hs-conid">()</span>
<span class="hs-definition">session</span> <span class="hs-varid">writeOut</span> <span class="hs-varid">inputXML</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
    <span class="hs-keyword">let</span> <span class="hs-varid">outputXML</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">formatG</span> <span class="hs-varop">$</span> <span class="hs-varid">indent</span> <span class="hs-num">2</span> <span class="hs-varop">$</span> <span class="hs-conid">Element</span> <span class="hs-str">"server"</span> <span class="hs-conid">[]</span> <span class="hs-layout">(</span><span class="hs-varid">processRoot</span> <span class="hs-varid">inputXML</span><span class="hs-layout">)</span>
    <span class="hs-varid">execute</span> <span class="hs-varop">$</span> <span class="hs-varid">liftIO</span> <span class="hs-varop">.</span> <span class="hs-varid">writeOut</span> <span class="hs-varop">=&lt;&lt;</span> <span class="hs-varid">outputXML</span>
    <span class="hs-varid">return</span> <span class="hs-conid">()</span></pre>
<strong>formatG</strong> is a <em>hexpat</em> function to take a tree node and format it as XML, returning one of Yair&#8217;s Lists of ByteStrings.  <strong>indent</strong> is a filter that adds pretty indenting.  The Element is the top level tag of our output XML tree, and its third argument &#8220;processRoot inputXML&#8221; evaluates the child nodes of the output document.  The entire processing of the document is in a functional style.</p>

<p><strong>execute</strong> here makes all the IO actually happen.  It iterates over a List of monadic actions and sequences them.  This translates into a sequence of writes of data blocks to the socket.  The elements in the list are monadic, so <strong>execute</strong> also must execute those in order to extract each output <strong>ByteString</strong>.</p>

<p>In this way, even though <strong>processRoot</strong> is pure at the top level, it can contain effectful computations.
<pre><span class="hs-definition">processRoot</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">ListOf</span> <span class="hs-layout">(</span><span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span><span class="hs-layout">)</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">ListOf</span> <span class="hs-layout">(</span><span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span><span class="hs-layout">)</span>
<span class="hs-definition">processRoot</span> <span class="hs-varid">root</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
    <span class="hs-conid">Element</span> <span class="hs-keyword">_</span> <span class="hs-keyword">_</span> <span class="hs-varid">children</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">genericTake</span> <span class="hs-num">1</span> <span class="hs-varid">root</span>
    <span class="hs-varid">child</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">children</span>
    <span class="hs-varid">extractElements</span> <span class="hs-varid">child</span>
  <span class="hs-keyword">where</span>
    <span class="hs-varid">extractElements</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">ListOf</span> <span class="hs-layout">(</span><span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span><span class="hs-layout">)</span>
    <span class="hs-varid">extractElements</span> <span class="hs-varid">elt</span> <span class="hs-keyglyph">|</span> <span class="hs-varid">isElement</span> <span class="hs-varid">elt</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">processCommand</span> <span class="hs-varid">elt</span> <span class="hs-varop">&#96;cons&#96;</span> <span class="hs-varid">mzero</span>
    <span class="hs-varid">extractElements</span> <span class="hs-keyword">_</span>                   <span class="hs-keyglyph">=</span> <span class="hs-varid">mzero</span></pre>
<strong>ListOf</strong> is a type function that conceals a long-winded type  name.  This function maps the input document to a list of output nodes.</p>

<p>The root of the input document is actually given as a <em>List</em> containing one item &#8211; the top-level XML tag.  The reason why we do this is so that we have to ask for it to be pulled.  If it were just passed as a <strong>UNode IO Text</strong> type, we would have to calculate it before the handler was called, and the handler wouldn&#8217;t get a chance to do output before it requests input.</p>

<p>The function is implemented using List&#8217;s Monad instance, which behaves exactly like a list monad.  The reason for <strong>genericTake 1 root</strong> is so we stop processing after the root node and don&#8217;t wait for a node that will never come.  I need to fix this in <em>hexpat-iteratee</em>.</p>

<p><strong>&#96;cons&#96;</strong> is the generalized list cons operator like <strong>:</strong> and  <strong>&#96;mzero&#96;</strong> corresponds to [].
<pre><span class="hs-definition">processCommand</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span>
<span class="hs-definition">processCommand</span> <span class="hs-varid">elt</span><span class="hs-keyglyph">@</span><span class="hs-layout">(</span><span class="hs-conid">Element</span> <span class="hs-str">"title"</span> <span class="hs-keyword">_</span> <span class="hs-keyword">_</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">Element</span> <span class="hs-str">"title"</span> <span class="hs-conid">[]</span> <span class="hs-varop">$</span> <span class="hs-varid">joinL</span> <span class="hs-varop">$</span> <span class="hs-keyword">do</span>
    <span class="hs-varid">txt</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">textContentM</span> <span class="hs-varid">elt</span>
    <span class="hs-varid">return</span> <span class="hs-varop">$</span> <span class="hs-varid">search</span> <span class="hs-varid">txt</span>
<span class="hs-definition">processCommand</span> <span class="hs-layout">(</span><span class="hs-conid">Element</span> <span class="hs-varid">cmd</span> <span class="hs-keyword">_</span> <span class="hs-keyword">_</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">Element</span> <span class="hs-str">"unknown"</span> <span class="hs-keyglyph">[</span><span class="hs-layout">(</span><span class="hs-str">"command"</span><span class="hs-layout">,</span> <span class="hs-varid">cmd</span><span class="hs-layout">)</span><span class="hs-keyglyph">]</span> <span class="hs-varid">mzero</span></pre>
Here is our command processor.  We have one command <strong>&lt;title&gt;foo&lt;/title&gt;</strong> that finds all movies whose titles contain <strong>foo</strong>.</p>

<p><strong>joinL</strong> is a bit of List magic that lets you drop down into the underlying monad, which in this case is <strong>XMLT IO a</strong>.  joinL&#8217;s type is <strong>::  ItemM l (l a) -&gt; l a </strong>where <strong>ItemM l</strong> is a type function giving the list&#8217;s monad.  So, the stuff after joinL resolves to a type of <strong>:: XMLT IO (ListOf (UNode IO Text))</strong>.
<pre><span class="hs-definition">search</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Text</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">ListOf</span> <span class="hs-layout">(</span><span class="hs-conid">UNode</span> <span class="hs-conid">IO</span> <span class="hs-conid">Text</span><span class="hs-layout">)</span>
<span class="hs-definition">search</span> <span class="hs-varid">key</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">joinL</span> <span class="hs-varop">$</span> <span class="hs-keyword">do</span>
    <span class="hs-varid">iter</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">liftIO</span> <span class="hs-varop">$</span> <span class="hs-varid">parse</span> <span class="hs-varid">defaultParserOptions</span> <span class="hs-varop">$</span> <span class="hs-keyglyph">\</span><span class="hs-varid">root</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-keyword">do</span>
        <span class="hs-keyword">let</span> <span class="hs-varid">l</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
                <span class="hs-varid">elt</span><span class="hs-keyglyph">@</span><span class="hs-layout">(</span><span class="hs-conid">Element</span> <span class="hs-keyword">_</span> <span class="hs-keyword">_</span> <span class="hs-varid">children</span><span class="hs-layout">)</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">genericTake</span> <span class="hs-num">1</span> <span class="hs-varid">root</span>
                <span class="hs-varid">movie</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-conid">List</span><span class="hs-varop">.</span><span class="hs-varid">filter</span> <span class="hs-varid">isElement</span> <span class="hs-varid">children</span>
                <span class="hs-varid">return</span> <span class="hs-varid">movie</span>
        <span class="hs-varid">execute</span> <span class="hs-varid">l</span>
        <span class="hs-varid">return</span> <span class="hs-varid">l</span>
    <span class="hs-varid">eMovies</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">liftIO</span> <span class="hs-varop">$</span> <span class="hs-varid">fileDriver</span> <span class="hs-varid">iter</span> <span class="hs-str">"movies.xml"</span>
    <span class="hs-keyword">case</span> <span class="hs-varid">eMovies</span> <span class="hs-keyword">of</span>
        <span class="hs-conid">Left</span> <span class="hs-varid">err</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-varid">fail</span> <span class="hs-varop">$</span> <span class="hs-str">"failed to read 'movies.xml': "</span><span class="hs-varop">++</span><span class="hs-varid">show</span> <span class="hs-varid">err</span>
        <span class="hs-conid">Right</span> <span class="hs-varid">movies</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-varid">return</span> <span class="hs-varop">$</span> <span class="hs-conid">List</span><span class="hs-varop">.</span><span class="hs-varid">filter</span> <span class="hs-varid">matches</span> <span class="hs-varid">movies</span>
  <span class="hs-keyword">where</span>
    <span class="hs-varid">matches</span> <span class="hs-varid">elt</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">key</span> <span class="hs-varop">&#96;</span><span class="hs-conid">T</span><span class="hs-varop">.</span><span class="hs-varid">isInfixOf</span><span class="hs-varop">&#96;</span> <span class="hs-varid">fromMaybe</span> <span class="hs-str">""</span> <span class="hs-layout">(</span><span class="hs-varid">getAttribute</span> <span class="hs-varid">elt</span> <span class="hs-str">"title"</span><span class="hs-layout">)</span></pre>
Here&#8217;s where our handler does some real I/O.  We read our database from a flat file using the same method of parsing.  Passing possibly unexecuted nodes outside the XMLT monad is a bit wrong, and needs to be addressed in the design, but here it works as long as I <strong>execute</strong> them.  Alternatively a pure XML parse would work.  <em>hexpat</em> has  functions to convert between pure and monadic node types.</p>

<p>So, I build and run the server, and here is the result, using Unix&#8217;s <strong>nc</strong> command as my client.  I typed this:
<pre>&lt;a&gt;
&lt;title&gt;of the&lt;/title&gt;</pre>
The output is:
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;server&gt;
 &lt;title&gt;
   &lt;movie id="dvzrwfvryd" disc="41" title="War of the Worlds (2005)"
        director="Steven Spielberg" genre="Sci Fi Thriller" rating="6"
        description="Tom Cruise alert" imdbID="tt0407304"/&gt;
   &lt;movie id="xxvjgxpokp" disc="44" title="Shaun of the Dead"
        director="Edgar Wright" genre="Comedy Horror" rating="8"
        description="British send-up zombie movie" imdbID="tt0365748"/&gt;
   &lt;movie id="duvcjsygqi" disc="104" title="March of the Penguins (La Marche de l&amp;apos;empereur)"
        director="Luc Jacquet" genre="Documentary" description="" imdbID="tt0428803"/&gt;
   &lt;movie id="dawcezoiro" disc="109" title="Pirates of the Caribbean: Dead Man&amp;apos;s Chest"
        director="Gore Verbinski" genre="Action/Comedy" rating="7" description="" imdbID="tt0383574"/&gt;
 &lt;/title&gt;</pre>
(New lines added for readability)</p>

<p>And the session can process more commands interactively.</p>

<p><strong>And pickled</strong></p>

<p>I should also mention my related <a href="http://hackage.haskell.org/package/hexpat-pickle">hexpat-pickle</a> package which is a shameless rip-off of the picklers from Uwe Schmidt&#8217;s excellent <a href="http://hackage.haskell.org/package/hxt">hxt</a> package.  I find it a very practical and quick way to bang out XML picklers.  (It doesn&#8217;t work with <em>hexpat-iteratee</em> yet.)</p>

<p><strong>Bye bye</strong></p>

<p>Here&#8217;s <a href="http://hip-to-be-square.com/~blackh/hexpat-iteratee-blog/">the code</a> in downloadable form.  Make sure you use the <strong>monads-fd</strong> and <strong>transformers</strong> packages instead of <strong>mtl</strong>.  Also <strong>hexpat-iteratee</strong> and <strong>text</strong>.</p>

<p>I hope you found this interesting.  I hope the XML haters of <strong>#haskell</strong> will be miraculously transformed into XML tolerators, and I hope you&#8217;ll help me improve <em>hexpat</em>. <em>&#8211; Stephen Blackheath, Manawatu, New Zealand</em></p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=157</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>AusHac2010: The inaugural Australian Haskell Hackathon!</title>
		<link>http://random.axman6.com/blog/?p=153</link>
		<comments>http://random.axman6.com/blog/?p=153#comments</comments>
		<pubDate>Mon, 22 Mar 2010 22:12:57 +0000</pubDate>
		<dc:creator>Axman6</dc:creator>
				<category><![CDATA[Haskell]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=153</guid>
		<description><![CDATA[Over the last week or so, Ivan Miljenovic and I have been busy organising AusHac2010. We&#8217;ve made a lot of progress, and are announcing the dates as the 16th-18th of July. If you&#8217;d like to come along and work on projects like:


    The LLVM backend to GHC
    the Accelerate, [...]]]></description>
			<content:encoded><![CDATA[<p>Over the last week or so, Ivan Miljenovic and I have been busy organising AusHac2010. We&#8217;ve made a lot of progress, and are announcing the dates as the 16th-18th of July. If you&#8217;d like to come along and work on projects like:</p>

<ul>
    <li>The LLVM backend to GHC</li>
    <li>the Accelerate, a Haskell EDSL for regular array computations, using various backends (CUDA, OpenCL, LLVM etc.) </li>
    <li> Hubris, the Haskell-Ruby binding</li>
    <li>Leksah, the Haskell IDE written in Haskell</li>
    <li>MPI bindings</li>
</ul>

<p>then please put your name down on the <a href="http://axman6.wufoo.com/forms/aushac-2010-sign-up/">sign up page</a>.</p>

<p>This should be a great opportunity for Aussie (and non aussie!) haskell hackers to come and meet all those people you know from Planet Haskell and #haskell, and give something back to the community, while having a great time.</p>

<p>Hope to see you there,
&#8211; Alex Mason</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=153</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A small follow up</title>
		<link>http://random.axman6.com/blog/?p=139</link>
		<comments>http://random.axman6.com/blog/?p=139#comments</comments>
		<pubDate>Thu, 07 Jan 2010 14:39:05 +0000</pubDate>
		<dc:creator>Axman6</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[bittorrent]]></category>
		<category><![CDATA[cereal]]></category>
		<category><![CDATA[parsing]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=139</guid>
		<description><![CDATA[In my previous post about why I love the cereal package, I went through the development of a bencoding parser and encoder. Brian was kind enough to point out some of the flaws I&#8217;d made in this code (which I should add had been caused from me not actually checking the spec while writing the [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous post about why I love the cereal package, I went through the development of a bencoding parser and encoder. Brian was kind enough to point out some of the flaws I&#8217;d made in this code (which I should add had been caused from me not actually checking the spec while writing the code, obviously a bad idea), and from these comments, I think I&#8217;ve managed to fix most of the problems:</p>

<blockquote>
Hi, thanks for writing this stuff. I think it could be pretty cool, but it could benefit from more precise reading and implementation of the spec.
<br/><br/>
For example, bencoded integers can be negative.
<br/><br/>
Also, my alarms go off whenever I see ‘read’. In ‘getBString’, you pass ‘read count’ to ‘getByteString’, which expects Int. But check, e.g., ‘read (show $ 2^64-1) :: Int’ in ghci. So if the torrent data is malformed, you could end up passing a negative length to ‘getByteString’. Maybe it knows how to deal with that, but it’s not something you should rely on.
<br/><br/>
You also have to decide what to do about dictionaries you read whose keys aren’t in order, etc.
<br/><br/>
Basically, please be more precise, especially if you put this on Hackage. This stuff is supposed to be industrial strength. Thanks.
</blockquote>

<p>The first problem, not handling negative integers was pretty trivial to fix, all I needed to do was check to see if there was a &#8216;-&#8217; char out the front, and if not, just get all the digits, and then read them:</p>

<p><pre><span class='hs-comment'>-- | Parses a BInt</span>
<span class='hs-definition'>getBInt</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Get</span> <span class='hs-conid'>BCode</span>
<span class='hs-definition'>getBInt</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>BInt</span> <span class='hs-varop'>.</span> <span class='hs-varid'>read</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>getWrapped</span> <span class='hs-chr'>'i'</span> <span class='hs-chr'>'e'</span> <span class='hs-varid'>intP</span>
    <span class='hs-keyword'>where</span> <span class='hs-varid'>intP</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-conop'>:</span><span class='hs-layout'>)</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>char</span> <span class='hs-chr'>'-'</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>getDigits</span><span class='hs-layout'>)</span> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>getDigits</span></pre></p>

<p>Brian also pointed out something I also wasn&#8217;t particularly happy with, the use of <code>read</code> to read in an Int64. This should under normal circumstances be more than large enough to read any bytestring that should be in any bencoded data (.torrent files are usually less than 1-200KB), so we should never have run into a problem here, but it&#8217;s still good to make sure we can be &#8216;industrial strength&#8217;:</p>

<p><pre><span class='hs-comment'>-- | Parses a BString</span>
<span class='hs-definition'>getBString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Get</span> <span class='hs-conid'>BCode</span>
<span class='hs-definition'>getBString</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
    <span class='hs-varid'>count</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>getDigits</span>
    <span class='hs-conid'>BString</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-layout'>(</span> <span class='hs-varid'>char</span> <span class='hs-chr'>':'</span> <span class='hs-varop'>*&gt;</span> <span class='hs-varid'>getStr</span> <span class='hs-layout'>(</span><span class='hs-varid'>read</span> <span class='hs-varid'>count</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Integer</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
    <span class='hs-keyword'>where</span> <span class='hs-varid'>maxInt</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromIntegral</span> <span class='hs-layout'>(</span><span class='hs-varid'>maxBound</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Integer</span>
          <span class='hs-varid'>getStr</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&gt;=</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>concat</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>sequence</span> <span class='hs-varop'>$</span> <span class='hs-varid'>getStr'</span> <span class='hs-varid'>n</span><span class='hs-layout'>)</span>
                   <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fail</span> <span class='hs-varop'>$</span> <span class='hs-str'>"read a negative length string, length: "</span> <span class='hs-varop'>++</span> <span class='hs-varid'>show</span> <span class='hs-varid'>n</span>
          <span class='hs-varid'>getStr'</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>n</span> <span class='hs-varop'>&gt;</span> <span class='hs-varid'>maxInt</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>getByteString</span> <span class='hs-varid'>maxBound</span> <span class='hs-conop'>:</span> <span class='hs-varid'>getStr'</span> <span class='hs-layout'>(</span><span class='hs-varid'>n</span><span class='hs-comment'>-</span><span class='hs-varid'>maxInt</span><span class='hs-layout'>)</span>
                    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>getByteString</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fromIntegral</span> <span class='hs-varop'>$</span> <span class='hs-varid'>n</span><span class='hs-keyglyph'>]</span></pre></p>

<p>Here you can see we&#8217;re now using an <code>Integer</code> as the read value, and taking chunks of <code>maxBound :: Int</code> bytes, until there are less than that many bytes left to fetch.</p>

<p>I&#8217;ve decided to ignore the problem with dictionaries with out of order elements, I can see this being something others may have overlooked in their implementations, and it&#8217;s entirely possible that other implementations do not put the keys in the right order. Our implementation does, but can easily handle malformed implementations. I see this is a bonus, and I hope others do too (I feel the code is more robust, and that&#8217;s always good).</p>

<p>I hope this has made some difference to the code, and what people think of it.</p>

<p>Until next time,</p>

<p>&#8211; Axman</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=139</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why I love Cereal</title>
		<link>http://random.axman6.com/blog/?p=124</link>
		<comments>http://random.axman6.com/blog/?p=124#comments</comments>
		<pubDate>Mon, 04 Jan 2010 15:11:08 +0000</pubDate>
		<dc:creator>Axman6</dc:creator>
				<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[binary]]></category>
		<category><![CDATA[bittorrent]]></category>
		<category><![CDATA[cereal]]></category>
		<category><![CDATA[parsing]]></category>

		<guid isPermaLink="false">http://random.axman6.com/blog/?p=124</guid>
		<description><![CDATA[Cereal, as you may know from my previous posts is a library for parsing binary data from strict ByteStrings. It is very similar to the binary package, but importantly, provides both an Alternative instance, and an Either String a return type for the decode function, which tells you where the parse failed.

I’ve been playing around [...]]]></description>
			<content:encoded><![CDATA[<p>Cereal, as you may know from my previous posts is a library for parsing binary data from strict ByteStrings. It is very similar to the binary package, but importantly, provides both an Alternative instance, and an <code>Either String a</code> return type for the decode function, which tells you where the parse failed.</p>

<p>I’ve been playing around with cereal lately in jlouis’ haskell-torrent project, rewriting the various binary parsing and producing parts of the program (the torrent file parser, and the wire protocol parser). I though it would be nice to share some of the code used for these, to demonstrate how easy cereal makes it to do such things.</p>

<p>To begin with, I’ll show you the part that decodes and encodes torrent files (if needed in the future). Torrent files are encoded using a very simple encoding, known as bencoding, which consists of four major primitives: Integral numbers, Strings of bytes, Arrays of bencoded objects, and Dictionaries of String, bencoded object pairs. This is very nicely represented using this datatype:
<pre><span class="hs-comment">-- | BCode represents the structure of a bencoded file</span>
<span class="hs-keyword">data</span> <span class="hs-conid">BCode</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">BInt</span> <span class="hs-conid">Integer</span>                       <span class="hs-comment">-- ^ An integer</span>
           <span class="hs-keyglyph">|</span> <span class="hs-conid">BString</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span>               <span class="hs-comment">-- ^ A string of bytes</span>
           <span class="hs-keyglyph">|</span> <span class="hs-conid">BArray</span> <span class="hs-keyglyph">[</span><span class="hs-conid">BCode</span><span class="hs-keyglyph">]</span>                     <span class="hs-comment">-- ^ An array</span>
           <span class="hs-keyglyph">|</span> <span class="hs-conid">BDict</span> <span class="hs-layout">(</span><span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-conid">Map</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span> <span class="hs-conid">BCode</span><span class="hs-layout">)</span>   <span class="hs-comment">-- ^ A key, value map</span>
  <span class="hs-keyword">deriving</span> <span class="hs-conid">Show</span></pre>
the specification for bencoded data goes something like this:</p>

<blockquote>Integers are encoded as the ASCII character for ‘i’ as a byte,
followed by the digits of the integral value, terminated by the
ASCII byte for ‘e’.
<blockquote>Eg: the number ‘42’ would be encoded as &#8220;i42e&#8221;</blockquote>
Strings are encoded as the digits of their length, followed by a
colon (‘:’), then the bytes of the string. these strings are really
just byte sequences, and probably shouldn’t be treated as having
an encoding (as jlouis and I found out when I tried to test the current
code on GHC 6.12.1, with the BString type using Strings, instead of
ByteStrings, and finding out that the simple test contained byte sequences
that could not be represented as Strings).
<blockquote>Eg: the string &#8220;hello&#8221; would become &#8220;5:hello&#8221;, &#8220;hello world&#8221; would
become &#8220;11:hello world&#8221;</blockquote>
Arrays are encoded as ASCII ‘l’ (for list I believe), followed by any
number of bencoded objects, terminated by an ASCII ‘e’. (This is where
using binary became difficult, as you had to explicitly check whether
you had reached the terminating ‘e’ using <code>lookAhead</code> when parsing before attempting
to parse another bencoded object, du the the lack of actual failure handling)
<blockquote>Eg: ["Hello", 123] would become &#8220;l5:helloi123ee&#8221;. Notice how we’ve used the
previous definitions for integral numbers, and strings.</blockquote>
Dictionaries are encoded as an ASCII ‘d’, followed by the String, object
pairs, followed by an ASCII ‘e’.
<blockquote>Eg: fromList [("test",123),("arr",[1,2,"hello"])] would become
&#8220;d4:testi123e3:arrli1ei2e5:helloee&#8221;.</blockquote>
It looks a bit of a mess, but it is quite efficient.</blockquote>

<h3 id="encoding">Encoding</h3>

<p>When writing my Serialize instance (Cereal’s version of the Binary class) for the BCode type, I decided it would be much easier to write the put methods first. This turned out to be rather straight forward, once I’d written a few helper functions.
<pre><span class="hs-definition">toW8</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Char</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Word8</span>
<span class="hs-definition">toW8</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">fromIntegral</span> <span class="hs-varop">.</span> <span class="hs-varid">ord</span></p>

<p><span class="hs-definition">fromW8</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Word8</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Char</span>
<span class="hs-definition">fromW8</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">chr</span> <span class="hs-varop">.</span> <span class="hs-varid">fromIntegral</span></p>

<p><span class="hs-definition">toBS</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">String</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span>
<span class="hs-definition">toBS</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-varid">pack</span> <span class="hs-varop">.</span> <span class="hs-varid">map</span> <span class="hs-varid">toW8</span></p>

<p><span class="hs-definition">fromBS</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-conid">ByteString</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">String</span>
<span class="hs-definition">fromBS</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">map</span> <span class="hs-varid">fromW8</span> <span class="hs-varop">.</span> <span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-varid">unpack</span></p>

<p><span class="hs-comment">-- | Put an element, wrapped by two characters</span>
<span class="hs-definition">wrap</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Char</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Char</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Put</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Put</span>
<span class="hs-definition">wrap</span> <span class="hs-varid">a</span> <span class="hs-varid">b</span> <span class="hs-varid">m</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
    <span class="hs-varid">putWord8</span> <span class="hs-layout">(</span><span class="hs-varid">toW8</span> <span class="hs-varid">a</span><span class="hs-layout">)</span>
    <span class="hs-varid">m</span>
    <span class="hs-varid">putWord8</span> <span class="hs-layout">(</span><span class="hs-varid">toW8</span> <span class="hs-varid">b</span><span class="hs-layout">)</span></p>

<p><span class="hs-comment">-- | Put something as it is shown using @show@</span>
<span class="hs-definition">putShow</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Show</span> <span class="hs-varid">a</span> <span class="hs-keyglyph">=&gt;</span> <span class="hs-varid">a</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Put</span>
<span class="hs-definition">putShow</span> <span class="hs-varid">x</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">mapM_</span> <span class="hs-varid">put</span> <span class="hs-layout">(</span><span class="hs-varid">show</span> <span class="hs-varid">x</span><span class="hs-layout">)</span></pre>
With these in hand, I set to work implementing the put function. The Integer and Array functions were straight forward:
<pre><span class="hs-keyword">instance</span> <span class="hs-conid">Serialize</span> <span class="hs-conid">BCode</span> <span class="hs-keyword">where</span>
     <span class="hs-varid">put</span> <span class="hs-layout">(</span><span class="hs-conid">BInt</span> <span class="hs-varid">i</span><span class="hs-layout">)</span>     <span class="hs-keyglyph">=</span> <span class="hs-varid">wrap</span> <span class="hs-chr">'i'</span> <span class="hs-chr">'e'</span> <span class="hs-varop">$</span> <span class="hs-varid">putShow</span> <span class="hs-varid">i</span>
     <span class="hs-varid">put</span> <span class="hs-layout">(</span><span class="hs-conid">BArray</span> <span class="hs-varid">arr</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">wrap</span> <span class="hs-chr">'l'</span> <span class="hs-chr">'e'</span> <span class="hs-varop">.</span> <span class="hs-varid">mapM_</span> <span class="hs-varid">put</span> <span class="hs-varop">$</span> <span class="hs-varid">arr</span></pre>
The Dictionary and String implementations weren’t too bad either:
<pre>    <span class="hs-varid">put</span> <span class="hs-layout">(</span><span class="hs-conid">BDict</span> <span class="hs-varid">mp</span><span class="hs-layout">)</span>   <span class="hs-keyglyph">=</span> <span class="hs-varid">wrap</span> <span class="hs-chr">'d'</span> <span class="hs-chr">'e'</span> <span class="hs-varid">dict</span>
                      <span class="hs-keyword">where</span> <span class="hs-varid">dict</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">mapM_</span> <span class="hs-varid">encPair</span> <span class="hs-varop">.</span> <span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">toList</span> <span class="hs-varop">$</span> <span class="hs-varid">mp</span>
                            <span class="hs-varid">encPair</span> <span class="hs-layout">(</span><span class="hs-varid">k</span><span class="hs-layout">,</span> <span class="hs-varid">v</span><span class="hs-layout">)</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">put</span> <span class="hs-layout">(</span><span class="hs-conid">BString</span> <span class="hs-varid">k</span><span class="hs-layout">)</span> <span class="hs-varop">&gt;&gt;</span> <span class="hs-varid">put</span> <span class="hs-varid">v</span>
     <span class="hs-varid">put</span> <span class="hs-layout">(</span><span class="hs-conid">BString</span> <span class="hs-varid">s</span><span class="hs-layout">)</span>  <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
                          <span class="hs-varid">putShow</span> <span class="hs-layout">(</span><span class="hs-conid">B</span><span class="hs-varop">.</span><span class="hs-varid">length</span> <span class="hs-varid">s</span><span class="hs-layout">)</span>
                          <span class="hs-varid">putWord8</span> <span class="hs-layout">(</span><span class="hs-varid">toW8</span> <span class="hs-chr">':'</span><span class="hs-layout">)</span>
                          <span class="hs-varid">putByteString</span> <span class="hs-varid">s</span></pre>
As you can see, the code is quite clear, and matches the specification quite well.</p>

<h3 id="decoding">Decoding</h3>

<p>Parsing the data was the next step. this proved a little more difficult, but with my recent (shallow) experience with Parsec, I knew what was needed.</p>

<p>I decided to start by writing some useful combinators (this is a lie, I wrote them when needed, but lying makes the post flow better &gt;_&gt;). These included the following:
<pre><span class="hs-comment">-- | Get a Char. Only works with single byte characters</span>
 <span class="hs-definition">getCharG</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-conid">Char</span>
 <span class="hs-definition">getCharG</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">fromW8</span> <span class="hs-varop">&lt;$&gt;</span> <span class="hs-varid">getWord8</span></p>

<p><span class="hs-comment">-- | Parse a given character</span>
 <span class="hs-definition">char</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Char</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Get</span> <span class="hs-conid">()</span>
 <span class="hs-definition">char</span> <span class="hs-varid">c</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
     <span class="hs-varid">x</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">getCharG</span>
     <span class="hs-keyword">if</span> <span class="hs-varid">x</span> <span class="hs-varop">==</span> <span class="hs-varid">c</span>
         <span class="hs-keyword">then</span> <span class="hs-varid">return</span> <span class="hs-conid">()</span>
         <span class="hs-keyword">else</span> <span class="hs-varid">fail</span> <span class="hs-varop">$</span> <span class="hs-str">"Expected char: '"</span> <span class="hs-varop">++</span> <span class="hs-varid">c</span><span class="hs-conop">:</span><span class="hs-str">"' got: '"</span> <span class="hs-varop">++</span> <span class="hs-keyglyph">[</span><span class="hs-varid">fromW8</span> <span class="hs-varid">x</span><span class="hs-layout">,</span><span class="hs-chr">'\''</span><span class="hs-keyglyph">]</span></p>

<p><span class="hs-comment">-- | Get something wrapped in two Chars</span>
 <span class="hs-definition">getWrapped</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Char</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Char</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Get</span> <span class="hs-varid">a</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Get</span> <span class="hs-varid">a</span>
 <span class="hs-definition">getWrapped</span> <span class="hs-varid">a</span> <span class="hs-varid">b</span> <span class="hs-varid">p</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">char</span> <span class="hs-varid">a</span> <span class="hs-varop"><em>&gt;</span> <span class="hs-varid">p</span> <span class="hs-varop">&lt;</em></span> <span class="hs-varid">char</span> <span class="hs-varid">b</span>
                  <span class="hs-comment">-- The same as char a &gt;&gt; p &gt;&gt;= \x -&gt; char b &gt;&gt; return x</span></p>

<p><span class="hs-comment">-- | Parse zero or items using a given parser</span>
 <span class="hs-definition">many</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-varid">a</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Get</span> <span class="hs-keyglyph">[</span><span class="hs-varid">a</span><span class="hs-keyglyph">]</span>
 <span class="hs-definition">many</span> <span class="hs-varid">p</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">many1</span> <span class="hs-varid">p</span> <span class="hs-varop"><code>mplus</code></span> <span class="hs-varid">return</span> <span class="hs-conid">[]</span></p>

<p><span class="hs-comment">-- | Parse one or more items using a given parser</span>
 <span class="hs-definition">many1</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-varid">a</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid">Get</span> <span class="hs-keyglyph">[</span><span class="hs-varid">a</span><span class="hs-keyglyph">]</span>
 <span class="hs-definition">many1</span> <span class="hs-varid">p</span> <span class="hs-keyglyph">=</span> <span class="hs-layout">(</span><span class="hs-conop">:</span><span class="hs-layout">)</span> <span class="hs-varop">&lt;$&gt;</span> <span class="hs-varid">p</span> <span class="hs-varop">&lt;*&gt;</span> <span class="hs-varid">many</span> <span class="hs-varid">p</span></p>

<p><span class="hs-comment">-- | Returns a character if it is a digit, fails otherwise. uses isDigit.</span>
 <span class="hs-definition">digit</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-conid">Char</span>
 <span class="hs-definition">digit</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
     <span class="hs-varid">x</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">getCharG</span>
     <span class="hs-keyword">if</span> <span class="hs-varid">isDigit</span> <span class="hs-varid">x</span>
         <span class="hs-keyword">then</span> <span class="hs-varid">return</span> <span class="hs-varid">x</span>
         <span class="hs-keyword">else</span> <span class="hs-varid">fail</span> <span class="hs-varop">$</span> <span class="hs-str">"Expected digit, got: "</span> <span class="hs-varop">++</span> <span class="hs-varid">show</span> <span class="hs-varid">x</span></p>

<p><span class="hs-comment">-- | Get one or more digit characters</span>
 <span class="hs-definition">getDigits</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-conid">String</span>
 <span class="hs-definition">getDigits</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">many1</span> <span class="hs-varid">digit</span></pre>
My favourite two definitions here are <code>many</code> and <code>many1</code>, which nicely show the use of Alternative: they are mutually recursive, with <code>many1</code> being the only one of the two to actually do and parsing, while <code>many</code> checks to see if <code>many1</code> failed to parse one object using the parser p. It’s really quite beautiful, and makes the code that follows a hell of a lot nicer to write. This is where the love mentioned in the title comes in by the way.</p>

<p>With these in hand, I could now go ahead and write the actual parsers for various BCode types. Parsing BInts and BArrays is dead simple now:
<pre><span class="hs-comment">-- | Parses a BInt</span>
 <span class="hs-definition">getBInt</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-conid">BCode</span>
 <span class="hs-definition">getBInt</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">BInt</span> <span class="hs-varop">.</span> <span class="hs-varid">read</span> <span class="hs-varop">&lt;$&gt;</span> <span class="hs-varid">getWrapped</span> <span class="hs-chr">'i'</span> <span class="hs-chr">'e'</span> <span class="hs-varid">getDigits</span></p>

<p><span class="hs-comment">-- | Parses a BArray</span>
 <span class="hs-definition">getBArray</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-conid">BCode</span>
 <span class="hs-definition">getBArray</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">BArray</span> <span class="hs-varop">&lt;$&gt;</span> <span class="hs-varid">getWrapped</span> <span class="hs-chr">'l'</span> <span class="hs-chr">'e'</span> <span class="hs-layout">(</span><span class="hs-varid">many</span> <span class="hs-varid">get</span><span class="hs-layout">)</span></pre>
As as side note, I’ve now come to see just what the folks on #haskell were on about when they said Applicative is nice. I think I’ve fallen in love (yet again!).</p>

<p>BStrings were a little more difficult, but not hard, given what I’ve just written:
<pre><span class="hs-comment">-- | Parses a BString</span>
 <span class="hs-definition">getBString</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-conid">BCode</span>
 <span class="hs-definition">getBString</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
     <span class="hs-varid">count</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">getDigits</span>
     <span class="hs-conid">BString</span> <span class="hs-varop">&lt;$&gt;</span> <span class="hs-layout">(</span> <span class="hs-varid">char</span> <span class="hs-chr">':'</span> <span class="hs-varop">*&gt;</span> <span class="hs-varid">getByteString</span> <span class="hs-layout">(</span><span class="hs-varid">read</span> <span class="hs-varid">count</span><span class="hs-layout">)</span><span class="hs-layout">)</span></pre>
Here we get as many digits as we can, followed by a colon, and then take the number of bytes the digits specified. Finally, we have the BDict definition, which also is quite nice, if slightly annoying with its use of pattern matching (don’t get me wrong, i love pattern matching, but it’s the only place it’s used in the parser <img src='http://random.axman6.com/blog/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  )
<pre><span class="hs-comment">-- | Parses a BDict</span>
 <span class="hs-definition">getBDict</span> <span class="hs-keyglyph">::</span> <span class="hs-conid">Get</span> <span class="hs-conid">BCode</span>
 <span class="hs-definition">getBDict</span> <span class="hs-keyglyph">=</span> <span class="hs-conid">BDict</span> <span class="hs-varop">.</span> <span class="hs-conid">M</span><span class="hs-varop">.</span><span class="hs-varid">fromList</span> <span class="hs-varop">&lt;$&gt;</span> <span class="hs-varid">getWrapped</span> <span class="hs-chr">'d'</span> <span class="hs-chr">'e'</span> <span class="hs-layout">(</span><span class="hs-varid">many</span> <span class="hs-varid">getPairs</span><span class="hs-layout">)</span>
     <span class="hs-keyword">where</span> <span class="hs-varid">getPairs</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword">do</span>
             <span class="hs-layout">(</span><span class="hs-conid">BString</span> <span class="hs-varid">s</span><span class="hs-layout">)</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">getBString</span>
             <span class="hs-varid">x</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid">get</span>
             <span class="hs-varid">return</span> <span class="hs-layout">(</span><span class="hs-varid">s</span><span class="hs-layout">,</span><span class="hs-varid">x</span><span class="hs-layout">)</span></pre>
Putting it all together, we finally have a definition for the get function in the Serialize class.
<pre>    <span class="hs-varid">get</span> <span class="hs-keyglyph">=</span> <span class="hs-varid">getBInt</span> <span class="hs-varop">&lt;|&gt;</span> <span class="hs-varid">getBArray</span> <span class="hs-varop">&lt;|&gt;</span> <span class="hs-varid">getBDict</span> <span class="hs-varop">&lt;|&gt;</span> <span class="hs-varid">getBString</span></pre>
A rather clean, elegant, and hopefully correct serialiser and deserialiser for the bencoded format used in torrent files. I’m considering releasing this code as a separate package on hackage, but I’m still not sure how widely it might be used. I have a string feeling that that would not be very wide at all, but that a library of more advanced combinators for cereal would make life a lot easier for others like me who have some strange binary formats that need to be parsed in an efficient manner.</p>

<p>Please, I implore you, do let me know what you think of this all, I’m always interested in seeing what others think of my code, and ways to improve it.</p>

<p>Until next time,</p>

<p>— Axman</p>
]]></content:encoded>
			<wfw:commentRss>http://random.axman6.com/blog/?feed=rss2&amp;p=124</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
