<?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/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">

<channel>
	<title>Paul Kuliniewicz</title>
	<atom:link href="http://www.kuliniewicz.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kuliniewicz.org/blog</link>
	<description>After all, it could only cost you your life, and you got that for free.</description>
	<lastBuildDate>Wed, 10 Mar 2010 03:40:24 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/us/</creativeCommons:license>		<item>
		<title>Mega Man 10</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/03/09/mega-man-10/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/03/09/mega-man-10/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 03:40:24 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Reviews]]></category>
		<category><![CDATA[mega man 10]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1768</guid>
		<description><![CDATA[Mega Man 9 was a great game.  It took everything that made the early NES Mega Man games terrific and built on them, and avoided the traps that made the latter games me-too rehashes of the same basic gameplay.  It played off of the player&#8217;s expectations of how a Mega Man game plays [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://megaman.wikia.com/wiki/Mega_Man_9">Mega Man 9</a> was a great game.  It took everything that made the early NES Mega Man games terrific and built on them, and avoided the traps that made the latter games me-too rehashes of the same basic gameplay.  It played off of the player&#8217;s expectations of how a Mega Man game plays out, slipping in traps to trick and surprise anyone who grew up playing the original games.  (And its increased difficulty modes in turn played off the player&#8217;s expectations from having played the game in normal mode, instead of just making enemies harder to destroy.)  The weapons are nicely varied and often have dual uses, such as <a href="http://megaman.wikia.com/wiki/Tornado_Blow">Tornado Blow</a> hurting all enemies on the screen <em>and</em> boosting your jumps a bit thanks to the updraft.  Mega Man 9 easily ranks in the same tier as <a href="http://megaman.wikia.com/wiki/Mega_Man_2">Mega Man 2</a>, one of the greatest games of all time, period.</p>
<p><a href="http://megaman.wikia.com/wiki/Mega_Man_10">Mega Man 10</a>, on the other hand, is a good game.  Not great, but good.  It&#8217;s a pretty solid game, but definitely not as innovative as its predecessor.</p>
<p>The weapons are somewhat harder to use effectively.  Several of them have a two-stage attack, and only the second stage deals significant damage.  For example, the <a href="http://megaman.wikia.com/wiki/Commando_Bomb">Commando Bomb</a>&#8217;s blast waves are more effective than hitting something with the bomb itself, and the <a href="http://megaman.wikia.com/wiki/Thunder_Wool">Thunder Wool</a>&#8217;s lightning bolt is much stronger than the cloud that rises up from Mega Man&#8217;s arm cannon to fire it.  It&#8217;s good to not have each weapon just be a differently-shaped projectile, but it can be tricky to aim for something <em>near</em> your target.</p>
<p>(Speaking of <a href="http://megaman.wikia.com/wiki/Sheep_Man">Sheep Man</a>, I get the distinct impression from playing the game that he was originally supposed to be something like Thunder Man.  They tried to make him look like a robotic cloud, but it wound up looking more like a robot sheep, so they ran with it.  It would certainly explain why Sheep Man&#8217;s stage is electricity-centric rather than pastoral.)</p>
<p>The individual stages aren&#8217;t bad, though the gimmicks in them aren&#8217;t quite as fun to play through as they were in Mega Man 9.  The disappearing blocks (heh heh) in Sheep Man&#8217;s stage are neat, but the see-saw thing in <a href="http://megaman.wikia.com/wiki/Blade_Man_%28Mega_Man_10%29">Blade Man</a>&#8217;s stage is more tedious than anything.  Some stages have branching paths, which is then taken to a bit of an extreme in <a href="http://megaman.wikia.com/wiki/Wily_Castle">Wily Castle</a> 1, where the branches themselves have branching paths.</p>
<p>I don&#8217;t think pointing out that Dr. Wily turns out to be the villain warrants a spoiler warning.</p>
<p>Wily Castle is the high point in the game.  The bosses in particular are pretty great, riffing on past games and, in one case, <a href="http://www.urbandictionary.com/define.php?term=giant+enemy+crab">a minor Internet meme?</a>  I really like the music for the Wily Castle bosses, and I think it goes particularly well with the <a href="http://megaman.wikia.com/wiki/Weapons_Archive">first one</a>.  I also suspect that anyone familiar with Mega Man 2 will do the exact wrong thing <a href="http://megaman.wikia.com/wiki/Picopico-Master">out of instinct</a> when they first encounter <a href="http://megaman.wikia.com/wiki/Block_Devil">Wily Castle 3&#8217;s boss</a>, like I did.  That&#8217;s the subverting-player-expectations thing that Mega Man 9 did so well.  And the final battle has a decent variant of the requisite fight against <a href="http://megaman.wikia.com/wiki/Wily_Capsule">Wily Capsule</a>.</p>
<p>By the way, Dr. Wily has tried to take over the world nine, or maybe ten, times already.  Who keeps issuing him building permits for new Wily Castles?  It&#8217;s not like he could build his latest Wily Castle in secret.</p>
<p>Why do I say nine or ten?  <a href="http://megaman.wikia.com/wiki/Mega_Man_and_Bass">Mega Man &amp; Bass</a> is a classic-series but unnumbered Mega Man game, so technically Mega Man 9 is the tenth in the series, and Mega Man 10 is the eleventh.  Mega Man 9 supports this by referencing each of its nine predecessors in its ending.  However, Mega Man 10 only calls out to the nine numbered classic-series games before it, completely ignoring Mega Man &amp; Bass.  And it&#8217;s not as though Inti Creates isn&#8217;t aware of Mega Man &amp; Bass, since they developed both Mega Man 9 and Mega Man 10.  It&#8217;s odd.</p>
<p>The plot makes no sense, even by the low standards of Mega Man games.  Ostensibly, Dr. Wily needs Mega Man and Proto Man&#8217;s help to recover the components of the Roboenza cure machine from the infected robot masters who stole it from his lab.  And it is reasonable to think a mad scientist who spends all his time making killer robots would be interested in not having them infected by a virus.  But it turns out that Dr. Wily was behind Roboenza all along!  So&#8230; why wouldn&#8217;t he already have the cure stockpiled somewhere, or design Roboenza so infected robots didn&#8217;t steal his stuff?  They were his robots, too, since they have <a href="http://megaman.wikia.com/wiki/Robot_Master#DWN_series">DWN-series</a> numbers.  Any why would he give Roll a functioning cure capsule, if he wants to trade the cure for robots&#8217; loyalty?  Or why not just use his close access to Mega Man and Proto Man to infect them directly?  Was Dr. Wily just hoping that Mega Man and Proto Man coming into close contact with the infected robot masters would cause them to catch Roboenza?  It seems needlessly indirect, especially when he&#8217;s right there in <a href="http://megaman.wikia.com/wiki/Dr._Light">Dr. Light</a>&#8217;s lab working on the cure machine.</p>
<p>Dr. Wily&#8217;s plan here makes the whole <a href="http://megaman.wikia.com/wiki/Mr._X">Mr. X</a> thing in <a href="http://megaman.wikia.com/wiki/Mega_Man_6">Mega Man 6</a> look downright genius by comparison.</p>
<p>Mega Man 10 does have an easy mode, which apparently has some people up in arms.  Normally I&#8217;d say &#8220;if you don&#8217;t like it, don&#8217;t play it&#8221;, but you <em>do</em> need to play through it to unlock some of the challenges, without which you can&#8217;t get 100% completion on those.  Easy mode also counts for the in-game challenges, which I&#8217;m not entirely sure I like.  My second play-through was on easy mode to unlock some of the challenge stages, and without trying too hard I passed the challenges for beating the game under an hour, beating the game without dying, <em>and</em> beating the game without using any <a href="http://megaman.wikia.com/wiki/E_Tank#Energy_Tank">E-</a>, <a href="http://megaman.wikia.com/wiki/E_Tank#Weapon_Tank">W-</a>, or <a href="http://megaman.wikia.com/wiki/E_Tank#Mystery_Tank">M-tanks</a>.  (Granted, though, I did go through a few Shock Guards &#8212; even easy mode can surprise you with spike traps.)  I&#8217;d like it better if the in-game challenges distinguished which difficulty level you beat them at, just like how some of the challenge stages distinguish between getting through the stage and getting through without taking damage.  But beating the game without taking damage would be difficult even on easy mode.  Doing it on hard mode&#8230; wow.</p>
<p>The challenge stages are a good way to practice fighting the game&#8217;s bosses without playing through the appropriate stage first, and they also give you a chance to practice with each special weapon and explore the full extent of its capabilities.  I wasn&#8217;t aware, for instance, you could use the <a href="http://megaman.wikia.com/wiki/Wheel_Cutter">Wheel Cutter</a> to climb walls, until I went through the challenge stage where it was needed.</p>
<p>If Mega Man 9 is on the same tier as Mega Man 2, I&#8217;d say Mega Man 10 is somewhere between the original <a href="http://megaman.wikia.com/wiki/Mega_Man_%28video_game%29">Mega Man</a> and <a href="http://megaman.wikia.com/wiki/Mega_Man_4">Mega Man 4</a>: still good, but a bit disappointing, especially when compared to its predecessor.  I&#8217;d be apprehensive about the prospect of a Mega Man 11, since it doesn&#8217;t look like they&#8217;re going to top Mega Man 9 anytime soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/03/09/mega-man-10/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rockman Paper Scissors</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/02/28/rockman-paper-scissors/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/02/28/rockman-paper-scissors/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 03:48:27 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Fanboyism]]></category>
		<category><![CDATA[mega man]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1764</guid>
		<description><![CDATA[Given that one of the core mechanics of the Mega Man series is the rock-paper-scissors style system of how each robot master is vulnerable to another robot master&#8217;s weapon, and given that the original game had robot masters that attacked by throwing rocks (Guts Man) and scissors (Cut Man) (and yes, rock beats scissors), it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Given that one of the core mechanics of the Mega Man series is the rock-paper-scissors style system of how each <a href="http://megaman.wikia.com/wiki/Robot_Master">robot master</a> is vulnerable to another robot master&#8217;s weapon, and given that the <a href="http://megaman.wikia.com/wiki/Mega_Man_%28video_game%29">original game</a> had robot masters that attacked by throwing <a href="http://megaman.wikia.com/wiki/Super_Arm">rocks</a> (<a href="http://megaman.wikia.com/wiki/Guts_Man">Guts Man</a>) and <a href="http://megaman.wikia.com/wiki/Rolling_Cutter">scissors</a> (<a href="http://megaman.wikia.com/wiki/Cut_Man">Cut Man</a>) (and yes, rock beats scissors), it&#8217;s surprising that there <em>still</em> has never been a paper-themed robot master.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/02/28/rockman-paper-scissors/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>School laptop spycams</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/02/24/school-laptop-spycams/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/02/24/school-laptop-spycams/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 21:58:46 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Links]]></category>
		<category><![CDATA[laptop]]></category>
		<category><![CDATA[spyware]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1761</guid>
		<description><![CDATA[In case you&#8217;ve heard about the school-issued laptops that surreptitiously took webcam photos of the students using them and are wondering just how something like that works, here&#8217;s the technical details of what the school-installed spyware was doing.
]]></description>
			<content:encoded><![CDATA[<p>In case you&#8217;ve heard about <a href="http://arstechnica.com/tech-policy/news/2010/02/school-under-fire-for-spying-on-kid-via-webcam-at-home.ars">the school-issued laptops that surreptitiously took webcam photos of the students using them</a> and are wondering just how something like that works, <a href="http://strydehax.blogspot.com/2010/02/spy-at-harrington-high.html">here&#8217;s the technical details of what the school-installed spyware was doing</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/02/24/school-laptop-spycams/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>I hate snow</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/02/06/i-hate-snow/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/02/06/i-hate-snow/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 03:28:57 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[snow]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1757</guid>
		<description><![CDATA[No, seriously, I hate snow.
Fun fact: do you know what a car buried under two feet of snow looks like?  Pretty much like anything else buried under two feet of snow.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.baltimoresun.com/news/weather/bal-maryland-snow-storm0206,0,6327465,full.story">No, seriously, I hate snow.</a></p>
<p>Fun fact: do you know what a car buried under two feet of snow looks like?  Pretty much like anything else buried under two feet of snow.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/02/06/i-hate-snow/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Panflute 0.6.1 released</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/01/31/panflute-0-6-1-released/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/01/31/panflute-0-6-1-released/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 20:24:18 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Panflute]]></category>
		<category><![CDATA[panflute]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1753</guid>
		<description><![CDATA[Panflute 0.6.1 has been released. This version adds support for rating songs in Banshee 1.5.3 or later, and fixes a few bugs. It also expands the types of song information that can be displayed in the applet.
]]></description>
			<content:encoded><![CDATA[<p><a href="https://launchpad.net/panflute">Panflute</a> <a href="https://launchpad.net/panflute/0.6/0.6.1">0.6.1</a> has been released. This version adds support for rating songs in <a href="http://banshee-project.org/">Banshee</a> 1.5.3 or later, and fixes a few bugs. It also expands the types of song information that can be displayed in the applet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/01/31/panflute-0-6-1-released/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Happstack and Streaming: Part 5: Modifying Happstack</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/01/29/happstack-and-streaming-part-5-modifying-happstack/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/01/29/happstack-and-streaming-part-5-modifying-happstack/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 15:00:25 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[happstack]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[streaming]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1745</guid>
		<description><![CDATA[Modifying Happstack
So now that we&#8217;ve established that changes to Happstack are needed to support streaming, what should those changes look like?  Abstractly, there needs to be a way to give it a series of chunks that it can send to the browser individually via chunked transfer encoding, flushing the network buffer after each one [...]]]></description>
			<content:encoded><![CDATA[<h3>Modifying Happstack</h3>
<p>So now that <a href="http://www.kuliniewicz.org/blog/archives/2010/01/27/happstack-and-streaming-part-4-the-flaw/">we&#8217;ve established that changes to Happstack are needed to support streaming</a>, what should those changes look like?  Abstractly, there needs to be a way to give it a series of chunks that it can send to the browser individually via chunked transfer encoding, flushing the network buffer after each one to make sure they&#8217;re sent promptly.</p>
<p>The most obvious way to do this is to add a third data constructor to the <code>Response</code> data type, for use with streams.  The main difference would be that, instead of accepting a single <code>ByteString</code> as the response to the browser, it would somehow get ahold of several.</p>
<p>What would that &#8220;somehow&#8221; be, though?  Looking back to our original motivation (the real-time multiplayer game being played in a web browser), the entire contents of the stream aren&#8217;t known at the time it starts, and its contents will be determined by the actions of the various players &#8212; i.e., things happening in the <code>IO</code> monad.  This means a simple list of <code>ByteString</code>s isn&#8217;t the way to go.  Although we did demonstrate such a list could be built anyway using some trickery, ideally we&#8217;d want something a bit more elegant, or at least one that doesn&#8217;t require actively subverting the type system via <code>unsafeInterleaveIO</code>.</p>
<p>Therefore we&#8217;d want to put an <code>IO</code> action in the response that could be used to generate new <code>ByteString</code>s on demand for each chunk.  The simplest way would be to use an <code>IO&nbsp;ByteString</code>:</p>
<div class="vim"><code><span class="Type">data</span> Response <span class="Statement">=</span> <span class="Comment">{&#0045; Response and SendFile data constructors&#0046;&#0046;&#0046; &#0045;}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">|</span> Chunked { rsCode&nbsp; &nbsp; &nbsp; <span class="Statement">::</span> Int,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsHeaders&nbsp;&nbsp; <span class="Statement">::</span> Headers,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsFlags&nbsp; &nbsp;&nbsp; <span class="Statement">::</span> RsFlags,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsValidator <span class="Statement">::</span> Maybe (Response <span class="Statement">&#0045;&gt;</span> IO Response),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chGenerator <span class="Statement">::</span> IO L&#0046;ByteString<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</code></div>
<p>Happstack could execute that action repeatedly to generate successive chunks, and we could even denote end-of-stream by having it produce an empty <code>ByteString</code>, which neatly parallels how chunked transfer encoding works.</p>
<p>An alternative would be something that includes an explicit state parameter that gets chained from one call to the <code>IO</code> action to the next.  Without something like that, it would be awkward (albeit not impossible) for the action to keep track of where it&#8217;s at in the stream and what it should generate next.</p>
<div class="vim"><code><span class="Type">data</span> Response a <span class="Statement">=</span> <span class="Comment">{&#0045; Response and SendFile data constructors&#0046;&#0046;&#0046; &#0045;}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">|</span> Chunked { rsCode&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; <span class="Statement">::</span> Int,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsHeaders&nbsp; &nbsp; &nbsp; <span class="Statement">::</span> Headers,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsFlags&nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">::</span> RsFlags,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsValidator&nbsp; &nbsp; <span class="Statement">::</span> Maybe (Response a <span class="Statement">&#0045;&gt;</span> IO (Response a)),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chGenerator&nbsp; &nbsp; <span class="Statement">::</span> a <span class="Statement">&#0045;&gt;</span> (a, IO L&#0046;ByteString),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chInitialState <span class="Statement">::</span> a<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</code></div>
<p>Unfortunately, that changes the <a href="http://en.wikipedia.org/wiki/Kind_%28type_theory%29">kind</a> of <code>Response</code> from <code>*</code> to <code>* &#0045;&gt; *</code> in order to account for the new type parameter <code>a</code> representing whatever state the stream wants to keep track of.  Since <code>Response</code> is used throughout Happstack and programs built on it, breaking <a href="http://en.wikipedia.org/wiki/Application_programming_interface">API</a> compatibility like that really ought to be avoided if we can help it, especially when it&#8217;s just for the sake of what would be an infrequently used feature.</p>
<p>Instead, what if we turn things around and put the generator in the driver&#8217;s seat: pass <em>it</em> an <code>IO</code> action to call whenever it has a new chunk ready to be sent:</p>
<div class="vim"><code><span class="Type">data</span> Response <span class="Statement">=</span> <span class="Comment">{&#0045; Response and SendFile data constructors&#0046;&#0046;&#0046; &#0045;}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">|</span> Chunked { rsCode&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; <span class="Statement">::</span> Int,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsHeaders&nbsp; &nbsp; &nbsp; <span class="Statement">::</span> Headers,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsFlags&nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">::</span> RsFlags,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsValidator&nbsp; &nbsp; <span class="Statement">::</span> Maybe (Response <span class="Statement">&#0045;&gt;</span> IO Response),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chGenerator&nbsp; &nbsp; <span class="Statement">::</span> (L&#0046;ByteString <span class="Statement">&#0045;&gt;</span> IO ()) <span class="Statement">&#0045;&gt;</span> IO ()<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</code></div>
<p>Happstack would invoke <code>chGenerator</code> with a function that handles writing a chunk to the network and doing whatever it needs to do when the stream is over.  The last thing <code>chGenerator</code> would do is call that function with an empty <code>ByteString</code> to signal end-of-stream.  <code>chGenerator</code> would be responsible for chaining any state information from one step to the next.  It would actually look rather like the pipe example from earlier; the function provided by Happstack would be used in place of <code>hPrint</code> and <code>hClose</code>, but other than that it&#8217;s the same basic idea.</p>
<p>There&#8217;s still the issue of signaling to the generator when it should stop because the network connection closed.  But hey, we&#8217;ve got a perfectly good return value from the Happstack-provided function that we&#8217;re not using.  Let&#8217;s use it:</p>
<div class="vim"><code><span class="Type">data</span> Response <span class="Statement">=</span> <span class="Comment">{&#0045; Response and SendFile data constructors&#0046;&#0046;&#0046; &#0045;}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">|</span> Chunked { rsCode&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; <span class="Statement">::</span> Int,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsHeaders&nbsp; &nbsp; &nbsp; <span class="Statement">::</span> Headers,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsFlags&nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">::</span> RsFlags,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rsValidator&nbsp; &nbsp; <span class="Statement">::</span> Maybe (Response <span class="Statement">&#0045;&gt;</span> IO Response),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chGenerator&nbsp; &nbsp; <span class="Statement">::</span> (L&#0046;ByteString <span class="Statement">&#0045;&gt;</span> IO Bool) <span class="Statement">&#0045;&gt;</span> IO ()<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</code></div>
<p>The Happstack-provided function returns <code>True</code> if more data should be generated, or <code>False</code> if it should be aborted.</p>
<p>That ought to work pretty well.  It addresses all the problems identified with our attempts to stream without changing Happstack.  The use of <code>Chunked</code> as the data constructor for the <code>Response</code> object will tell Happstack to suppress the <tt>Content-Length</tt> header, use chunked transfer encoding, and flush the network buffer after each chunk.  New data to stream is only generated as needed, without using additional threads or large buffers.  API compatibility with existing code is preserved; we&#8217;re adding a new interface and leaving existing ones untouched.  Even better, there&#8217;s no need to use any trickery to achieve lazy IO; with Happstack&#8217;s cooperation, the usual kind of IO works just fine.</p>
<p>Mind you, I haven&#8217;t written a patch that implements this proposal.  It&#8217;s just an idea.  At the very least, I&#8217;d want to have one realistic application (i.e., not a simple proof-of-concept like from earlier) that demonstrates how it can be used and to verify that it does indeed work correctly before actually submitting a patch.  After all, as any good programmer can tell you, sometimes flaws in a design don&#8217;t become apparent until you actually try to implement them.  But it <em>seems</em> like this ought to work.</p>
<p>Now I just have to get around to writing the application whose idea motivated me to investigate the feasibility of streaming data from Happstack to begin with.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/01/29/happstack-and-streaming-part-5-modifying-happstack/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Happstack and Streaming: Part 4: The Flaw</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/01/27/happstack-and-streaming-part-4-the-flaw/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/01/27/happstack-and-streaming-part-4-the-flaw/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 15:00:47 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[happstack]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[streaming]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1741</guid>
		<description><![CDATA[The Fatal Flaw
All three approaches to generating a lazy ByteString from the IO monad actually do work, as you can verify by loading the source code into ghci and invoking them manually.  However, if you go through the web server and visit one of the finite stream paths, no output will appear until the [...]]]></description>
			<content:encoded><![CDATA[<h3>The Fatal Flaw</h3>
<p>All <a href="http://www.kuliniewicz.org/blog/archives/2010/01/25/happstack-and-streaming-part-3-implementation-sort-of/">three approaches</a> to generating a lazy <code>ByteString</code> from the <code>IO</code> monad actually do work, as you can verify by loading the source code into <tt>ghci</tt> and invoking them manually.  However, if you go through the web server and visit one of the finite stream paths, no output will appear until the stream has finished being generated, at which point the entire set of output from the server will arrive all at once, like so:</p>
<blockquote><p><tt>paul@queeg:~/tmp$ GET &#0045;es http://localhost:8000/pipe/limited<br /></tt><br />
<i>(nothing happens for a while, and then&#8230;)</i><br />
<tt>200 OK<br />
Connection: close<br />
Date: Mon, 18 Jan 2010 13:30:55 GMT<br />
Server: Happstack/0&#0046;4&#0046;1<br />
Content&#0045;Type: te&#120;t/html; charset=utf&#0045;8<br />
Client&#0045;Date: Mon, 18 Jan 2010 13:30:58 GMT<br />
Client&#0045;Peer: 127&#0046;0&#0046;0&#0046;1:8000<br />
Client&#0045;Response&#0045;Num: 1<br />
&nbsp;<br />
2010&#0045;01&#0045;18 13:30:55&#0046;342444 UTC<br />
2010&#0045;01&#0045;18 13:30:55&#0046;443235 UTC<br />
2010&#0045;01&#0045;18 13:30:55&#0046;544115 UTC<br />
2010&#0045;01&#0045;18 13:30:55&#0046;644934 UTC<br />
2010&#0045;01&#0045;18 13:30:55&#0046;745514 UTC<br />
2010&#0045;01&#0045;18 13:30:55&#0046;846283 UTC<br />
2010&#0045;01&#0045;18 13:30:55&#0046;947581 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;048834 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;150068 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;251281 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;352521 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;454423 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;555816 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;657179 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;758547 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;859939 UTC<br />
2010&#0045;01&#0045;18 13:30:56&#0046;961296 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;062581 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;163847 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;265212 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;366438 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;4677 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;569059 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;670414 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;772045 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;873404 UTC<br />
2010&#0045;01&#0045;18 13:30:57&#0046;974761 UTC<br />
2010&#0045;01&#0045;18 13:30:58&#0046;076117 UTC<br />
2010&#0045;01&#0045;18 13:30:58&#0046;177485 UTC<br />
2010&#0045;01&#0045;18 13:30:58&#0046;278847 UTC<br />
</tt></p></blockquote>
<p>The point where the delay occurs reveals what&#8217;s going on &#8212; not even the headers are getting sent out until the entire response has been generated.  That&#8217;s not Happstack&#8217;s doing; it&#8217;s the buffering happening inside the networking library.  In the absence of any command to send data out immediately, it&#8217;s going to wait until it has a large chunk it can send out immediately.  Sending one large packet instead of lots of small packets makes more efficient use of network bandwidth, since each packet carries its own overhead.  And since Happstack wasn&#8217;t written with streaming in mind, it doesn&#8217;t flush the buffer until it&#8217;s written out the complete response.</p>
<p>As further evidence, the infinite streams do stream, kind of.  Once the buffer fills up, the networking library will push it out to make room for more data.  As a result, nothing will arrive for a while, then all of a sudden lots of data will arrive, then another long pause as the buffer fills back up, then another big chunk of data, and so on.</p>
<p>This alone shows why, despite our best efforts at cleverly creating the response, it&#8217;s all for nothing unless we can control the buffering behavior down in the network library, which Happstack doesn&#8217;t provide any access to.  The only exception would be if we&#8217;re trying to stream data quickly enough to rapidly fill up the buffer, but since there&#8217;s also no way to control the size of the buffer, that &#8220;solution&#8221; isn&#8217;t reliable, and certainly not applicable if we&#8217;re only trying to stream a relative trickle of information.</p>
<h3>Buffering Strikes Back</h3>
<p>Buffering introduces additional problems that, while they don&#8217;t kill the solution outright, adds some significant inefficiencies.  These are easiest to see with the infinite streams, which continue until the browser closes the connection.  (They&#8217;d also arise any time the browser closes a finite stream before receiving all the data.)</p>
<p>First, Happstack only detects that the connection to the browser has been closed once the network library tries to send out data and returns an error.  Between the time when the connection actually closes (i.e. when the browser sends a TCP FIN packet) and the time when Happstack notices, the program continues generating new data to send.  All this effort is wasted, since the data will never get sent out and will be thrown away.  The app server winds up doing a lot of useless work as a result.</p>
<p>Being able to control network-level buffering would largely deal with this problem too: since a closed connection is detected when trying to send data, sending each chunk out immediately would allow the app server to stop generating the stream much more promptly.  If that were the case, the approach of manually using <code>unsafeInterleaveIO</code>, despite being the most difficult of the three, would work fairly well.  The other two, however, have their own buffering problems, independent of what&#8217;s happening at the network level.</p>
<p>For example, what is a pipe but a buffer being managed by the operating system?  Since a separate thread is writing data to the pipe independently of the thread reading from it, the generation thread will keep on going even if the network connection closes, until the pipe fills up.  In theory the OS should cause writes to fail as soon as the read end of the pipe is closed, but using lazy IO to read from it seems to keep this from happening promptly.  The generation thread will keep writing more data to the pipe until it too gets a write error and stops.</p>
<p>Using channels is even worse.  The network buffer and the pipe at least have the benefit of being of finite size; once they fill up, further attempts to write will block until something reads the data back out or an error is detected and the buffer is destroyed.  Channels, however, are <em>unbounded</em>.  They never fill up; they just keep growing to make room for new data as it&#8217;s written.  As a result, in the event of the browser closing the connection prematurely, the size of the channel will grow and grow until the thread writing data to it decides to stop.  This is a problem for the infinite streams, since they <em>never</em> stop; eventually the channel will grow to consume all available memory on the system until the OS kills the app server entirely.  This is also a problem for finite streams, of course, since those channels won&#8217;t get thrown away until they grow to the size of the unconsumed portion of the stream, which would be a big problem if the app server is generating lots of streams.</p>
<h3>Playing Nice</h3>
<p>But even if all the buffering problems can be dealt with, our solution <em>still</em> is far less than ideal.  While the idea of slowly trickling out the stream&#8217;s data as it becomes available is legal according to the definition of HTTP, it&#8217;s really not the proper way to go about it.</p>
<p>Remember how we had to suppress the <tt>Content-Length</tt> header?  Browsers use that header to know when they can stop reading the response from the server.  Without it, the only way they can tell they&#8217;ve received all the data is when the server closes the connection.  Leaving the connection open has the advantage that the browser can re-use it for the next request it sends to the server, instead of creating a new connection.  Establishing a new connection requires doing the <a href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment">TCP three-way handshake</a> again, which involves a round trip to the server that doesn&#8217;t carry any data.  Being able to reuse the connection is faster since this extra round trip is eliminated.  It might not seem like much, but consider a web page that has lots of small graphics on it; without being able to reuse a connection, a new round trip is needed <em>every time</em> the browser tries to download another image.  All those little delays add up.</p>
<p>It turns out HTTP does have a way to stream data while still telling the browser how much data to expect: <a href="http://en.wikipedia.org/wiki/Chunked_transfer_encoding">chunked transfer encoding</a>.  Basically, the server&#8217;s response gets split up into separate chunks, and each chunks carries its own length information.  The end of the stream is indicated by a zero-length chunk.  With chunked transfer encoding, the browser knows when it&#8217;s finished receiving the data, even though the server doesn&#8217;t necessarily know how much data will be sent beforehand.</p>
<p>Chunked transfer encoding is what we&#8217;d want the server to be able to do.  Of course, Happstack would need to be modified to support it, since it too needs to know when the stream has ended so it can reuse the connection for the next request from the browser.</p>
<p>In Part 5, we&#8217;ll look at just what sort of modifications we might try to make.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/01/27/happstack-and-streaming-part-4-the-flaw/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happstack and Streaming: Part 3: Implementation (Sort Of)</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/01/25/happstack-and-streaming-part-3-implementation-sort-of/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/01/25/happstack-and-streaming-part-3-implementation-sort-of/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 15:00:27 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[happstack]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[streaming]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1732</guid>
		<description><![CDATA[Implementation
For our proof-of-concept for trying to do streaming with Happstack, here&#8217;s a simple web application that implements each of the three possible approaches discussed earlier.  To keep things simple, the data we&#8217;ll be streaming is a series of timestamps taken from the system clock at regular intervals.  Not a particularly useful application, but [...]]]></description>
			<content:encoded><![CDATA[<h3>Implementation</h3>
<p>For our <a href="http://www.kuliniewicz.org/blog/archives/2010/01/22/happstack-and-streaming-part-2-lazy-io/">proof-of-concept for trying to do streaming with Happstack</a>, here&#8217;s a simple web application that implements each of the three possible approaches discussed earlier.  To keep things simple, the data we&#8217;ll be streaming is a series of timestamps taken from the system clock at regular intervals.  Not a particularly useful application, but it is something simple that uses IO, which is all we&#8217;re looking for here.  To make things a bit more interesting, the web app will support each approach two different ways: first, streaming a finite number of timestamp values before ending the stream, and second, streaming an endless series of timestamp values until the browser closes the connection.</p>
<p>Specifically, the web app will support the following six paths:</p>
<dl>
<dt><tt>/pipe/limited</tt></dt>
<dd>A finite number of timestamps, using a OS-level pipe.</dd>
<dt><tt>/pipe/infinite</tt></dt>
<dd>An infinite number of timestamps, using an OS-level pipe.</dd>
<dt><tt>/chan/limited</tt></dt>
<dd>A finite number of timestamps, using a <code>Chan</code>.</dd>
<dt><tt>/chan/infinite</tt></dt>
<dd>An infinite number of timestamps, using a <code>Chan</code>.</dd>
<dt><tt>/manual/limited</tt></dt>
<dd>A finite number of timestamps, using <code>unsafeInterleaveIO</code> manually.</dd>
<dt><tt>/manual/infinite</tt></dt>
<dd>An infinite number of timestamps, using <code>unsafeInterleaveIO</code> manually.</dd>
</dl>
<p>First, let&#8217;s get all the module imports out of the way.  There&#8217;s nothing particularly interesting about any of them, so I won&#8217;t comment on them further.</p>
<div class="vim"><code><span class="Special">{&#0045;# LANGUAGE Fle&#120;ibleConte&#120;ts #&#0045;}</span><br />
&nbsp;<br />
<span class="Type">module</span> Main (main) <span class="Type">where</span><br />
&nbsp;<br />
<span class="PreProc">import</span> Control&#0046;Concurrent (forkIO, threadDelay)<br />
<span class="PreProc">import</span> Control&#0046;Concurrent&#0046;Chan (Chan, getChanContents, newChan, writeChan)<br />
<span class="PreProc">import</span> Control&#0046;Monad (liftM, MonadPlus, msum, when)<br />
<span class="PreProc">import</span> Control&#0046;Monad&#0046;Trans (liftIO, MonadIO)<br />
<span class="PreProc">import</span> Data&#0046;Time&#0046;Clock (diffUTCTime, getCurrentTime)<br />
<span class="PreProc">import</span> Happstack&#0046;Server&#0046;HTTP&#0046;Types (Method (&#0046;&#0046;), noContentLength, nullConf, Response, resultBS)<br />
<span class="PreProc">import</span> Happstack&#0046;Server&#0046;SimpleHTTP (dir, FilterMonad, internalServerError, methodSP, nullDir,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ServerMonad, simpleHTTP, toResponse)<br />
<span class="PreProc">import</span> System&#0046;IO (Handle, hClose, hFlush, hPrint, hPutStrLn, stderr)<br />
<span class="PreProc">import</span> System&#0046;IO&#0046;Unsafe (unsafeInterleaveIO)<br />
<span class="PreProc">import</span> System&#0046;Posi&#120;&#0046;IO (createPipe, fdToHandle)<br />
&nbsp;<br />
<span class="PreProc">import</span> <span class="PreProc">qualified</span> Data&#0046;ByteString&#0046;Char8 <span class="PreProc">as</span> S<br />
<span class="PreProc">import</span> <span class="PreProc">qualified</span> Data&#0046;ByteString&#0046;Lazy&#0046;Char8 <span class="PreProc">as</span> L</code></div>
<p>Next is the code that sets up the Happstack server with the six paths mentioned above.</p>
<div class="vim"><code>main <span class="Statement">::</span> IO ()<br />
main <span class="Statement">=</span> simpleHTTP nullConf root<br />
&nbsp;<br />
root <span class="Statement">::</span> (ServerMonad m, MonadPlus m, MonadIO m, FilterMonad Response m) <span class="Statement">=&gt;</span> m Response<br />
root <span class="Statement">=</span> msum [ dir <span class="Constant">&quot;pipe&quot;</span>&nbsp;&nbsp; <span class="Statement">$</span> subdir outputPipe<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , dir <span class="Constant">&quot;chan&quot;</span>&nbsp;&nbsp; <span class="Statement">$</span> subdir outputChan<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , dir <span class="Constant">&quot;manual&quot;</span> <span class="Statement">$</span> subdir outputManual<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ]<br />
&nbsp;<br />
subdir <span class="Statement">::</span> (ServerMonad m, MonadPlus m, MonadIO m) <span class="Statement">=&gt;</span> ((Int <span class="Statement">&#0045;&gt;</span> Int) <span class="Statement">&#0045;&gt;</span> IO Response) <span class="Statement">&#0045;&gt;</span> m Response<br />
subdir output <span class="Statement">=</span> msum [ dir <span class="Constant">&quot;limited&quot;</span>&nbsp; <span class="Statement">$</span> nullDir <span class="Statement">&gt;&gt;</span> methodSP GET (liftIO <span class="Statement">$</span> output decr)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; , dir <span class="Constant">&quot;infinite&quot;</span> <span class="Statement">$</span> nullDir <span class="Statement">&gt;&gt;</span> methodSP GET (liftIO <span class="Statement">$</span> output id)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; ]<br />
&nbsp; &nbsp; <span class="Type">where</span> decr n <span class="Statement">=</span> n <span class="Statement">&#0045;</span> <span class="Constant">1</span></code></div>
<p>To support both finite and infinite streams, each stream generator takes an initial counter and a decrement function.  After generating each timestamp value, it applies the decrement function to the counter, and stops if the counter reaches zero.  For finite streams, the decrement function subtracts one from the counter.  For infinite streams, it does nothing, so that the counter never reaches zero.</p>
<p>Yeah, it&#8217;s kind of an ugly hack, but it&#8217;s good enough for this.</p>
<p>Here&#8217;s the code for generating a stream using OS-level pipes:</p>
<div class="vim"><code>outputPipe <span class="Statement">::</span> (Int <span class="Statement">&#0045;&gt;</span> Int) <span class="Statement">&#0045;&gt;</span> IO Response<br />
outputPipe decr <span class="Statement">=</span> <span class="Statement">do</span> h <span class="Statement">&lt;&#0045;</span> pipeClock decr limitedCount<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; bs <span class="Statement">&lt;&#0045;</span> L&#0046;hGetContents h<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; return <span class="Statement">$</span> streamBS bs<br />
&nbsp;<br />
pipeClock <span class="Statement">::</span> (Int <span class="Statement">&#0045;&gt;</span> Int) <span class="Statement">&#0045;&gt;</span> Int <span class="Statement">&#0045;&gt;</span> IO Handle<br />
pipeClock decr n <span class="Statement">=</span> <span class="Statement">do</span> (readFd, writeFd) <span class="Statement">&lt;&#0045;</span> createPipe<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writeH <span class="Statement">&lt;&#0045;</span> fdToHandle writeFd<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; forkIO <span class="Statement">$</span> output writeH n <span class="Statement">`catch`</span> abort writeH<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fdToHandle readFd<br />
&nbsp; &nbsp; <span class="Type">where</span> output h <span class="Constant">0</span> <span class="Statement">=</span> <span class="Statement">do</span> hPutStrLn stderr <span class="Constant">&quot;closing pipe&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hClose h<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output h n <span class="Statement">=</span> <span class="Statement">do</span> now <span class="Statement">&lt;&#0045;</span> getCurrentTime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hPrint h now<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hFlush h<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tick now<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; threadDelay interval<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output h (decr n)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; abort h e <span class="Statement">=</span> <span class="Statement">do</span> hPutStrLn stderr <span class="Statement">$</span> <span class="Constant">&quot;caught error: &quot;</span> <span class="Statement">++</span> show e<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; hClose h</code></div>
<p>The above code creates a pipe.  A new thread is forked off to repeatedly write timestamps into the pipe.  For a finite stream, the new thread closes its end of the pipe when it&#8217;s done writing.  Meanwhile, the original thread uses lazy IO to read the entire contents of the pipe into a lazy <code>ByteString</code>, which gets passed back down to Happstack for sending to the browser.</p>
<p>Here&#8217;s the code for generating a stream using an IO channel:</p>
<div class="vim"><code>outputChan <span class="Statement">::</span> (Int <span class="Statement">&#0045;&gt;</span> Int) <span class="Statement">&#0045;&gt;</span> IO Response<br />
outputChan decr <span class="Statement">=</span> <span class="Statement">do</span> ch <span class="Statement">&lt;&#0045;</span> chanClock decr limitedCount<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; chunks <span class="Statement">&lt;&#0045;</span> getChanContents ch<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; <span class="Statement">let</span> bs <span class="Statement">=</span> L&#0046;fromChunks <span class="Statement">$</span> takeWhile (not <span class="Statement">&#0046;</span> S&#0046;null) chunks<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; return <span class="Statement">$</span> streamBS bs<br />
&nbsp;<br />
chanClock <span class="Statement">::</span> (Int <span class="Statement">&#0045;&gt;</span> Int) <span class="Statement">&#0045;&gt;</span> Int <span class="Statement">&#0045;&gt;</span> IO (Chan S&#0046;ByteString)<br />
chanClock decr n <span class="Statement">=</span> <span class="Statement">do</span> ch <span class="Statement">&lt;&#0045;</span> newChan<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; forkIO <span class="Statement">$</span> output ch n<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ch<br />
&nbsp; &nbsp; <span class="Type">where</span> output ch <span class="Constant">0</span> <span class="Statement">=</span> <span class="Statement">do</span> hPutStrLn stderr <span class="Constant">&quot;done writing to channel&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; writeChan ch S&#0046;empty<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output ch n <span class="Statement">=</span> <span class="Statement">do</span> now <span class="Statement">&lt;&#0045;</span> getCurrentTime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; writeChan ch <span class="Statement">$</span> chunkify now<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; tick now<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; threadDelay interval<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; output ch (decr n)</code></div>
<p>The above code does the same basic thing, just with a channel of strict <code>ByteString</code>s instead of a pipe.  A new thread is forked off to write timestamp values to the channel.  For a finite stream, the new thread writes an empty <code>ByteString</code> to indicate that it&#8217;s done.  Meanwhile, the orginal thread uses lazy IO to read the entire contents of the channel into a (lazy) list, up until an empty <code>ByteString</code>.  It then lazily combines the individual strict <code>ByteString</code>s into a single lazy <code>ByteString</code> that it then passes down to Happstack.</p>
<p>The two above approaches each use a new thread that writes a timestamp, waits for the specified interval, writes another timestamp, and so on.  Thus, the two code snippets look pretty similar in basic structure.  Not so for using <code>unsafeInterleaveIO</code> directly:</p>
<div class="vim"><code>outputManual <span class="Statement">::</span> (Int <span class="Statement">&#0045;&gt;</span> Int) <span class="Statement">&#0045;&gt;</span> IO Response<br />
outputManual decr <span class="Statement">=</span> <span class="Statement">do</span> bs <span class="Statement">&lt;&#0045;</span> manualClock decr limitedCount<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; return <span class="Statement">$</span> streamBS bs<br />
&nbsp;<br />
manualClock <span class="Statement">::</span> (Int <span class="Statement">&#0045;&gt;</span> Int) <span class="Statement">&#0045;&gt;</span> Int <span class="Statement">&#0045;&gt;</span> IO L&#0046;ByteString<br />
manualClock decr n <span class="Statement">=</span> <span class="Statement">do</span> now <span class="Statement">&lt;&#0045;</span> getCurrentTime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tick now<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allFutureChunks <span class="Statement">&lt;&#0045;</span> unsafeInterleaveIO <span class="Statement">$</span> ticksAfter now<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">let</span> futureChunks <span class="Statement">=</span> map fst <span class="Statement">$</span> zip allFutureChunks countdown<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return <span class="Statement">&#0046;</span> L&#0046;fromChunks <span class="Statement">$</span> chunkify now <span class="Statement">:</span> futureChunks<br />
&nbsp; &nbsp; <span class="Type">where</span> ticksAfter since <span class="Statement">=</span> <span class="Statement">do</span> now <span class="Statement">&lt;&#0045;</span> getCurrentTime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">let</span> delta <span class="Statement">=</span> diffUTCTime now since<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; when (delta <span class="Statement">&lt;</span> interval <span class="Statement">/</span> <span class="Constant">1000000</span>) <span class="Statement">$</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; threadDelay (round (interval <span class="Statement">&#0045;</span> delta <span class="Statement">*</span> <span class="Constant">1000000</span>))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; now' <span class="Statement">&lt;&#0045;</span> getCurrentTime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tick now'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; futureChunks <span class="Statement">&lt;&#0045;</span> unsafeInterleaveIO <span class="Statement">$</span> ticksAfter now'<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return <span class="Statement">$</span> chunkify now' <span class="Statement">:</span> futureChunks<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; countdown <span class="Statement">=</span> takeWhile (<span class="Statement">&gt;</span> <span class="Constant">0</span>) <span class="Statement">$</span> iterate decr (decr n)</code></div>
<p>Here, all the action takes place in a single thread.  Again, it takes the strategy of combining a bunch of strict <code>ByteString</code>s, one per timestamp, into a lazy <code>ByteString</code> with everything.  It generates the first timestamp immediately, but defers building the rest of the list until it&#8217;s needed.  When it is needed, it again generates the first timestamp of the rest of the list immediately, and defers building the rest.</p>
<p>It&#8217;s worth noting that this approach is the most difficult to write, since putting <code>unsafeInterleaveIO</code> in the right place is critical to making it work.  Also, since everything is happening in a single thread, strictly speaking it&#8217;s no longer good enough to just delay for the desired interval between timestamps, since there&#8217;s no telling how much time has been spent in other parts of the code.  Instead, it needs to check the clock <em>twice</em> each time around: first to figure out how long to delay, if any, and second to actually get the timestamp.  Not surprisingly, the code is also the hardest to read of the three.</p>
<p>Finally, there are some odds and ends that bear mentioning.  Here&#8217;s a simple function that converts a time value into a strict <code>ByteString</code>:</p>
<div class="vim"><code>chunkify <span class="Statement">::</span> Show a <span class="Statement">=&gt;</span> a <span class="Statement">&#0045;&gt;</span> S&#0046;ByteString<br />
chunkify <span class="Statement">=</span> S&#0046;pack <span class="Statement">&#0046;</span> (<span class="Statement">++</span> <span class="Constant">&quot;</span><span class="Special">&#0092;n</span><span class="Constant">&quot;</span>) <span class="Statement">&#0046;</span> show</code></div>
<p>Here&#8217;s a helper function that prints out a message whenever a new timestamp is generated, so we can watch the app server&#8217;s progress:</p>
<div class="vim"><code>tick <span class="Statement">::</span> Show a <span class="Statement">=&gt;</span> a <span class="Statement">&#0045;&gt;</span> IO ()<br />
tick &#120; <span class="Statement">=</span> hPutStrLn stderr <span class="Statement">$</span> <span class="Constant">&quot;tick &quot;</span> <span class="Statement">++</span> show &#120;</code></div>
<p>As you can see from the type signatures of those two utility functions, there&#8217;s nothing that makes them unique to time values; <em>any</em> value that can be converted to a string (i.e., anything belonging to the <code>Show</code> class), works.  We just happen to only use them with <code>UTCTime</code>s.</p>
<p>Anyway, here&#8217;s a simple function for converting a lazy <code>ByteString</code> into the <code>Response</code> object that Happstack ultimately wants:</p>
<div class="vim"><code>streamBS <span class="Statement">::</span> L&#0046;ByteString <span class="Statement">&#0045;&gt;</span> Response<br />
streamBS <span class="Statement">=</span> noContentLength <span class="Statement">&#0046;</span> resultBS <span class="Constant">200</span></code></div>
<p>We explicitly tell Happstack not to add the <tt>Content-Length</tt> header, since to do that it would need to measure the length of the entire response, which would mean it can&#8217;t send anything until it sees the entire response, which defeats the entire point of what we&#8217;re trying to accomplish.</p>
<p>Last, and also least, here are the constants specifying the time interval between timestamps, and how many timestamps to generate in a finite stream before stopping:</p>
<div class="vim"><code>interval <span class="Statement">::</span> Num a <span class="Statement">=&gt;</span> a<br />
interval <span class="Statement">=</span> <span class="Constant">100000</span>&nbsp; &nbsp; &nbsp; &nbsp; <span class="Comment">&#0045;&#0045; microseconds</span><br />
&nbsp;<br />
limitedCount <span class="Statement">::</span> Num a <span class="Statement">=&gt;</span> a<br />
limitedCount <span class="Statement">=</span> <span class="Constant">30</span></code></div>
<p>That&#8217;s the entirety of the code.  If you have <a href="http://www.haskell.org/ghc/">GHC</a> installed, you can go ahead and compile the program and play around with it to find out whether or not any of the approaches we&#8217;ve tried actually work.  Since we didn&#8217;t pass any configuration parameters to Happstack, it will start a web server on port 8000 that you can point your favorite browser to, at any of the six paths we defined.</p>
<p>Stay tuned for <a href="http://www.kuliniewicz.org/blog/archives/2010/01/27/happstack-and-streaming-part-4-the-flaw/">Part 4</a>, where we&#8217;ll see why (spoiler alert!) none of the three approaches actually work.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/01/25/happstack-and-streaming-part-3-implementation-sort-of/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Happstack and Streaming: Part 2: Lazy IO</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/01/22/happstack-and-streaming-part-2-lazy-io/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/01/22/happstack-and-streaming-part-2-lazy-io/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 15:00:31 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[happstack]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[streaming]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1728</guid>
		<description><![CDATA[Two Haskell features complicate our attempt at streaming data from Happstack: lazy evaluation, and its handling of IO.
Laziness
Unlike more mainstream languages, Haskell evaluates expressions lazily; it doesn&#8217;t actually compute the value until it&#8217;s actually used.  This has some interesting benefits.  For example, it&#8217;s quite easy to create infinitely long lists without requiring infinite [...]]]></description>
			<content:encoded><![CDATA[<p>Two Haskell features complicate <a href="http://www.kuliniewicz.org/blog/archives/2010/01/20/happstack-and-streaming-part-1-introduction/">our attempt at streaming data from Happstack</a>: lazy evaluation, and its handling of IO.</p>
<h3>Laziness</h3>
<p>Unlike more mainstream languages, Haskell <a href="http://en.wikipedia.org/wiki/Lazy_evaluation">evaluates expressions lazily</a>; it doesn&#8217;t actually compute the value until it&#8217;s actually used.  This has some interesting benefits.  For example, it&#8217;s quite easy to create infinitely long lists without requiring infinite amounts of memory.  For example, the expression <code>[1&nbsp;..]</code> is a list of <em>all</em> positive integers.  Haskell code can pass that infinite list around like any other value, and as long as we don&#8217;t do something that requires actually trying to evaluate the entire list (such as trying to compute its <code>length</code>), we&#8217;re perfectly safe.</p>
<p>We can even do computations where we create multiple infinitely long lists and do operations on the entire thing, as long as we never try to use the entire result.  For example, here we take the aforementioned infinitely long list, split it up into evens and odds, add the two infinitely long lists pairwise, and look for the first element greater than 5,000:</p>
<div class="vim"><code>foo <span class="Statement">::</span> Integer<br />
foo <span class="Statement">=</span> head greaterThan5000<br />
&nbsp; &nbsp; <span class="Type">where</span> greaterThan5000 <span class="Statement">=</span> filter (<span class="Statement">&gt;</span> <span class="Constant">5000</span>) sums<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sums&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">=</span> zipWith (<span class="Statement">+</span>) odds evens<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; odds&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="Statement">=</span> filter odd positives<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; evens&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; <span class="Statement">=</span> filter even positives<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; positives&nbsp; &nbsp; &nbsp;&nbsp; <span class="Statement">=</span> [<span class="Constant">1</span> <span class="Statement">&#0046;&#0046;</span>]</code></div>
<p>The five lists defined in the <code>where</code> clause above are all infinitely long, but that&#8217;s OK because the program never needs to evaluate more than a finite part of any of them to compute the value of <code>foo</code>.  (For the record, it&#8217;s 5003.)</p>
<p>So, problem solved, right?  The application server just needs to give Happstack a <code>ByteString</code><code>, which after all is just a compacted list of <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Data-Word.html#t%3AWord8">Word8</a></code>s or <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Data-Char.html#t%3AChar">Char</a>s, and that list can evaluate to the data we eventually want to send to the browser, once we figure out in the future what it needs to be.</p>
<p>Sadly, it&#8217;s not <em>that</em> easy; you&#8217;re forgetting another key property of Haskell that lets lazy evaluation work.</p>
<h3>Pure Functional IO</h3>
<p>Lazy evaluation works because Haskell is a <a href="http://en.wikipedia.org/wiki/Purely_functional">purely functional</a> language: expressions do not have <a href="http://en.wikipedia.org/wiki/Side_effect_%28computer_science%29">side effects</a>.  As a result, <a href="http://en.wikipedia.org/wiki/Function_%28computer_science%29">functions in Haskell</a> are much like <a href="http://en.wikipedia.org/wiki/Function_%28mathematics%29">functions in mathematics</a>: their output is entirely determined by their input parameters, and their only result is producing a new value.  Haskell functions can&#8217;t reference any values whose value might change, since values in a Haskell program <em>never</em> change.  This is why lazy evaluation works: it doesn&#8217;t matter <em>when</em> the program gets around to evaluating an expression, if ever, since its result will always be exactly the same.</p>
<p>However, this seems to prevent a Haskell program from interacting with the outside world, since the system running a Haskell program, much like the rest of the universe, is not purely functional.  Any operation that interacts with the world outside the Haskell program could be affected by whatever happens to be going on at the time the operation is run.</p>
<p>As a simple example, consider the <code>time()</code> function in <a href="http://en.wikipedia.org/wiki/C_%28programming_language%29">C</a> programming on Linux.  <code>time()</code> returns the current time on the system, and will obviously return a different result depending on what time it is when it gets called.  Reading from a file is similar; the result returned will depend on what&#8217;s stored in the file at the time it&#8217;s read, which could change if something else writes to the file.</p>
<p>Interaction with the outside world is needed for a program to do anything useful, so how does Haskell get around this?  Via a bit of trickery known as the <code>IO</code> monad.  <a href="http://www.haskell.org/all_about_monads/html/index.html">Monads</a> can be a bit tricky to get your head around initially, but basically they&#8217;re just a way to sequence operations, with the monad doing something to take the output on one operation and give it as input to the next.  The particular monad being used gets to decide what &#8220;sequencing operations&#8221; means, as though you could redefine what the semicolon means in C.  Although most monads have a way to both put values into and take values out of a monad, the <code>IO</code> monad only lets you put values in.  Although you can also run a function on the value inside the <code>IO</code> monad, the result will itself also be in the <code>IO</code> monad.  There is no escape from the <code>IO</code> monad.</p>
<p>What&#8217;s the point?  Conceptually, the <code>IO</code> monad is just another type of <a href="http://www.haskell.org/all_about_monads/html/statemonad.html">state monad</a>, which carries another value (the state) from one operation to the next.  In the <code>IO</code> monad&#8217;s case, that state is merely the state of the entire universe outside the Haskell program.  Anything needing to interact with the outside world runs inside the <code>IO</code> monad, which as a result orders those operations into a particular sequence.</p>
<p>What does this have to do with anything?  Recall from earlier that our use case is streaming the current state of an interactive game as it changes over time in response to input from the players over a network.  That input-over-a-network is IO and thus runs inside the <code>IO</code> monad, and thus too must anything that uses the result.  So really, our hypothetical function that creates the data to stream back to the browser doesn&#8217;t &#8212; <em>can&#8217;t</em> &#8212; just return a result of type <code>ByteString</code>.  No, it has to return a result of type <code>IO ByteString</code>.</p>
<p>The good news is, the function the application server implements for Happstack to create a <code>Response</code> runs in the <code>IO</code> monad, so this is legal.  The bad news is that the <code>IO</code> monad truly <em>sequences</em> operations: the entirety of our hypothetical result-creating function has to execute <em>before</em> the result can be given to Happstack to send it to the browser.  Either the result-creating function returns right away, and thus can never see the result of other players&#8217; actions later, or it waits until those are handled, and can&#8217;t return anything until the game is over.</p>
<p>It seems that the rules of the <code>IO</code> monad prevent us from making this work.  </p>
<p><a href="http://www.youtube.com/watch?v=FbS4EvZuw1M#t=2m27s">Screw the rules, I have <strike>money</strike></a> lazy IO!</p>
<h3>Lazy IO</h3>
<p>Lazy IO lets a program bend the rules of lazy evaluation and <code>IO</code> sequencing a bit.  For example, consider the <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Prelude.html#v%3AreadFile"><code>readFile</code> function</a> in the Haskell standard library, whose type is the following:</p>
<div class="vim"><code>readFile <span class="Statement">::</span> FilePath <span class="Statement">&#0045;&gt;</span> IO String</code></div>
<p>Superficially, this seems to read the entire file in memory before returning, per the rules of the <code>IO</code> monad.  Which would make the following program extremely ill-advised:</p>
<div class="vim"><code><span class="PreProc">import</span> Data&#0046;Char (ord)<br />
&nbsp;<br />
main <span class="Statement">::</span> IO ()<br />
main <span class="Statement">=</span> <span class="Statement">do</span> zeroes <span class="Statement">&lt;&#0045;</span> readFile <span class="Constant">&quot;/dev/zero&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print <span class="Statement">&#0046;</span> take <span class="Constant">20</span> <span class="Statement">$</span> map ord zeroes</code></div>
<p>It reads in the contents of the file <a href="http://en.wikipedia.org/wiki//dev/zero"><code>/dev/zero</code></a>, converts the characters to their <a href="http://en.wikipedia.org/wiki/Unicode">Unicode</a> code point values, and prints the first 20 of them.  However, on any Unix-ish system, <code>/dev/zero</code> is a file that contains an <em>infinite</em> number of zero bytes.  A program can read from it as long as it wants, and never reach the end.</p>
<p>The Haskell program, of course, doesn&#8217;t know about this property of <code>/dev/zero</code>, yet <code>readFile</code> doesn&#8217;t try to read an endless series of bytes into memory.  Why not?  Because <code>readFile</code> is a bit special; it does its IO lazily.</p>
<p><code>readFile</code> isn&#8217;t alone.  The <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Control-Concurrent-Chan.html#v%3AgetChanContents"><code>getChanContents</code></a> function is similar:</p>
<div class="vim"><code>getChanContents <span class="Statement">::</span> Chan a <span class="Statement">&#0045;&gt;</span> IO [a]</code></div>
<p>It takes an object of type <code>Chan a</code> &#8212; a thread-safe unbounded queue of objects of an arbitrary type &#8212; and returns an infinite list of all items that are currently in the channel, as well as all items which will ever be written to the channel <em>in the future</em>.  It, too, does lazy IO.</p>
<p>How can this be?  If you dig into the source code of how these and similar functions are implemented (thanks to <a href="http://haskell.org/ghc/license.html">the Glasgow Haskell Compiler&#8217;s open-source license</a>, you can easily do this), and trace through the calls they make, you ultimately come to this interesting little function:</p>
<div class="vim"><code>unsafeInterleaveIO <span class="Statement">::</span> IO a <span class="Statement">&#0045;&gt;</span> IO a</code></div>
<p>The <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/System-IO-Unsafe.html#v%3AunsafeInterleaveIO"><code>unsafeInterleaveIO</code></a> function converts any normal <code>IO</code> computation into a lazy one: one that executes not when the <code>IO</code> action would normally run, but instead when its value is actually used.  It is implemented using the <a href="http://en.wikipedia.org/wiki/Deep_magic">deeply magic</a> function named <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/System-IO-Unsafe.html#v%3AunsafePerformIO"><code>unsafePerformIO</code></a>, which takes that &#8220;nothing ever escapes the <code>IO</code> monad&#8221; rule and punches it in the face:</p>
<div class="vim"><code>unsafePerformIO <span class="Statement">::</span> IO a <span class="Statement">&#0045;&gt;</span> a</code></div>
<p>As you might guess from the fact that their names both start with the word &#8220;unsafe&#8221;, and that they&#8217;re in the module named <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/System-IO-Unsafe.html"><code>System.IO.Unsafe</code></a>, these functions are dangerous, since they let you bypass Haskell&#8217;s usual efforts to make lazy evaluation and IO not stab each other in the back.  In certain cases, lazy IO can be mostly safe.  For example, with <code>readFile</code>, you&#8217;re usually in trouble anyway if program A is reading a file while program B is writing it.  As long as nothing is actively writing to a file, it doesn&#8217;t matter whether it gets read <a href="http://en.wikipedia.org/wiki/Eager_evaluation">eagerly</a> or lazily, since the data will be the same either way.</p>
<p>Of course, you&#8217;re better off using the functions that use <code>unsafeInterleaveIO</code> and friends rather than using them directly.  As a general rule, you&#8217;re taking matter into your own hands when you use functions prefixed by the word &#8220;unsafe&#8221;.  As the saying goes, if it breaks, you get to keep the pieces.</p>
<p>However, the existence of lazy IO offers a few possibilities for how we might try to make streaming work without modifying Happstack, thanks to lazy IO.</p>
<ol>
<li>Use an OS-level pipe.  Pipes have two ends: one for writing data into it, and one for reading data out of it.  Once they&#8217;re created, each end of a pipe can be treated like any other file.  Fork a thread to write data to the pipe, which the original thread lazily reads back out as a <code>ByteString</code>.</li>
<li>Use a <code>Chan</code>.  Fork a thread to write data to the channel, which the original thread lazily reads and builds a <code>ByteString</code> from.</li>
<li>Use <code>unsafeInterleaveIO</code> directly to lazily generate the <code>ByteString</code> as needed.</li>
</ol>
<p>You know, this is starting to look like it might actually work.  I won&#8217;t mention the crippling flaw shared by each of these options, however, at least not just yet.  (They also each share a second, non-crippling but still significant flaw; a careful reading of <a href="http://tools.ietf.org/html/rfc2616">RFC 2616</a> might give you a clue what it is, if you can&#8217;t bear the suspense.)  It&#8217;s better if we try implementing them and experience how and why they each fail, as will any approach that doesn&#8217;t involve modifying Happstack somehow.</p>
<p>We&#8217;ll start doing precisely that in <a href="http://www.kuliniewicz.org/blog/archives/2010/01/25/happstack-and-streaming-part-3-implementation-sort-of/">Part 3</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/01/22/happstack-and-streaming-part-2-lazy-io/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Happstack and Streaming: Part 1: Introduction</title>
		<link>http://www.kuliniewicz.org/blog/archives/2010/01/20/happstack-and-streaming-part-1-introduction/</link>
		<comments>http://www.kuliniewicz.org/blog/archives/2010/01/20/happstack-and-streaming-part-1-introduction/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 03:16:24 +0000</pubDate>
		<dc:creator>Paul Kuliniewicz</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[happstack]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[streaming]]></category>

		<guid isPermaLink="false">http://www.kuliniewicz.org/blog/?p=1721</guid>
		<description><![CDATA[Introduction
The question: is it possible to use Happstack to serve streaming data?
Spoiler alert: the answer is &#8220;no&#8221;.  At least, not with the current version of Happstack (0.4.1).  However, exploring the reasons why it isn&#8217;t possible sheds some light on what changes you&#8217;d need to make to Happstack to make it work.  This [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>The question: is it possible to use <a href="http://happstack.com/">Happstack</a> to serve streaming data?</p>
<p>Spoiler alert: the answer is &#8220;no&#8221;.  At least, not with the current version of Happstack (0.4.1).  However, exploring the reasons <em>why</em> it isn&#8217;t possible sheds some light on what changes you&#8217;d need to make to Happstack to make it work.  This five-part series will explore that topic in some detail, including code that almost-but-not-quite does what we want.</p>
<h3>What is streaming, anyway?</h3>
<p>For this discussion, I&#8217;m talking about generating a series of bytes in real time from a web application server and sending those bytes to a web browser as part of a single <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">HTTP</a> response message.</p>
<p>This is different from simply sending a large file to the browser.  In that case, file already exists on the disk, and can simply be read from and sent across the network as quickly as the client can keep up.  <a href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a> automatically takes care of all the ugly details of how you do that reliably; from the application server&#8217;s perspective, you send the whole thing in one giant chunk and let the network worry about the rest.</p>
<p>Here, however, the bytes we want to send <em>aren&#8217;t</em> known ahead of time.  The <a href="http://en.wikipedia.org/wiki/Use_case">use case</a> I have in mind is a browser-based game where the current game state changes continuously.  It&#8217;d be nice to have the server send all those updates as part of a single response, with the browser acting on updates as they are received.  The alternative is to have the browser repeatedly poll for updates, sending a brand new request each time it wants the latest information.  Polling is more complicated to implement because the browser now needs to worry about timing its update requests, instead of just letting the server send them when an update is ready.  (Recall that HTTP uses a <a href="http://en.wikipedia.org/wiki/Client-server">client/server</a>, <a href="http://en.wikipedia.org/wiki/Request-response">request/response</a> model, preventing the server from sending data to the browser without the browser first asking for it.)</p>
<p>The game scenario is what prevents the server from knowing what bytes will be sent to the browser beforehand, since the game state depend on what moves the players make as the game progresses.  To stream updates, the server needs to start sending the response before it knows what all the data that will be included in it are.</p>
<p>Thus the question: if we use Happstack to write the web application server implementing the game, is streaming updates over a single response even possible?</p>
<h3>Happstack model</h3>
<p>The core part of any application written for Happstack is a function that takes the request from the browser and returns a <a href="http://happstack.com/docs/0.4/happstack-server/Happstack-Server-HTTP-Types.html#t%3AResponse"><code>Response</code> object</a> that gets sent back to the browser.  (Granted, that&#8217;s a very simplified version of what you pass to <a href="http://happstack.com/docs/0.4/happstack-server/Happstack-Server-SimpleHTTP.html#v%3AsimpleHTTP"><code>simpleHTTP</code></a>, but it&#8217;s good enough for our discussion here.)  Happstack takes care of all the details of actually sending and receiving data over the network, converting things into <a href="http://www.haskell.org/">Haskell</a> objects, and the like.</p>
<p>In Happstack 0.4.1, there are two kinds of <code>Response</code>s, only the first of which is of concern to us.  (The <a href="http://happstack.com/docs/0.4/happstack-server/Happstack-Server-HTTP-Types.html#v%3ASendFile">second kind</a> is optimized for sending existing a preexisting file to the browser, which precisely not what we want.)  A <code>Response</code> is really just a <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/bytestring-0.9.1.5/Data-ByteString-Lazy.html">(lazy) <code>ByteString</code></a>, along with HTTP metadata like a <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">status code</a> and a set of <a href="http://en.wikipedia.org/wiki/List_of_HTTP_headers">headers</a>.  Happstack provides a lot of tools to help set it all up, but ultimately the application is responsible for providing the <code>ByteString</code> to be sent to the browser.  Once we give Happstack that <code>ByteString</code>, it&#8217;s out of the application&#8217;s hands.</p>
<p>At first glance, this seems to preclude us from returning any kind of real-time stream.  After all, how can the application possibly return a value that it can&#8217;t compute until some point in the <em>future</em>?  That doesn&#8217;t just sound difficult; it sounds physically <em>impossible</em>.</p>
<p>Actually, it turns out that&#8217;s the easy part, as we&#8217;ll see in <a href="http://www.kuliniewicz.org/blog/archives/2010/01/22/happstack-and-streaming-part-2-lazy-io/">Part 2</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kuliniewicz.org/blog/archives/2010/01/20/happstack-and-streaming-part-1-introduction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
