<?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:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Brain Crater</title>
	<atom:link href="http://braincrater.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://braincrater.wordpress.com</link>
	<description>Thoughts from my splattered grey matter.</description>
	<lastBuildDate>Wed, 08 Jun 2011 19:19:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='braincrater.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Brain Crater</title>
		<link>http://braincrater.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://braincrater.wordpress.com/osd.xml" title="Brain Crater" />
	<atom:link rel='hub' href='http://braincrater.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Ajax Chat App using Yesod</title>
		<link>http://braincrater.wordpress.com/2010/07/22/ajax-chat-app-using-yesod/</link>
		<comments>http://braincrater.wordpress.com/2010/07/22/ajax-chat-app-using-yesod/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 02:17:46 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[1]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[yesod]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=65</guid>
		<description><![CDATA[I&#8217;ve finally recovered from fourth year enough that I feel like coding a serious personal project again. That project is a turn-based tabletop game I&#8217;m adapting to code, I&#8217;ll go into more detail about it later. For the interface, I want to do an Ajax-powered web app, and I&#8217;m using Michael Snoyman&#8217;s excellent Haskell web [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=65&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve finally recovered from fourth year enough that I feel like coding a serious personal project again. That project is a turn-based tabletop game I&#8217;m adapting to code, I&#8217;ll go into more detail about it later. For the interface, I want to do an Ajax-powered web app, and I&#8217;m using Michael Snoyman&#8217;s excellent Haskell web framework, Yesod, to make that happen.</p>
<p>There&#8217;s Ajax support built into Yesod, but nothing for push updates sent to clients. In order to prove that Yesod (and I) were up to the job, I wrote a basic many-user chat room app. It uses the fairly standard hack for Ajax push: clients send a dummy request and the server just leaves the connection open, and uses the response as a form of push.</p>
<p>The code, both the Haskell and the Javascript (uses jQuery), follows. I&#8217;m not going to bother explaining how Yesod works, Michael Snoyman has already done an excellent job of that at <a href="http://docs.yesodweb.com">docs.yesodweb.com</a>. This is basically a combination of the Ajax and &#8220;Chat&#8221; (really a message board) tutorials from there. The only tricky part is that the site argument, a read-only parameter passed to request handlers by Yesod, contains a couple of TVars that hold one duplicate of a single TChan for each client (<code>dupTChan</code> is awesome for this kind of independent-read/broadcast-write application). </p>
<p>Clients send an Ajax request to post a message, of course, but they also make a check-in request. That handler (<code>getCheckR</code>) finds that client&#8217;s TChan and blocks until data is available on it, which it then sends to the client. The clients displays it and makes another check-in request.</p>
<p>That leads me to my question to my readers: The Javascript function <code>checkIn</code> makes an Ajax request whose callback calls <code>checkIn</code> again. Is that a safe thing to do? Does it leak stack frames? It depends, I suppose, on the internals of jQuery&#8217;s implementation, and possibly on the Javascript engine. If anyone could enlighten me, I would be very grateful.</p>
<p>Edit: You may have noticed that WordPress mangled the code below. It&#8217;s also out of date with the modern versions of Yesod. A cleaned up and modernized version of my code can be found in the <a href="http://hackage.haskell.org/package/yesod-examples-0.8.0.1" title="yesod-examples">yesod-examples</a> package.</p>
<pre>
{-# LANGUAGE TemplateHaskell, QuasiQuotes, TypeFamilies #-}

module Main where

import Yesod
import Yesod.Helpers.Static

import Control.Concurrent.STM
import Control.Concurrent.STM.TChan
import Control.Concurrent.STM.TVar

import Control.Arrow ((***))

-- speaker and content
data Message = Message String String

-- all those TChans are dupes, so writing to any one writes to them all, but reading is separate
data Chat = Chat
  { chatClients    :: TVar [(Int, TChan Message)]
  , nextClient     :: TVar Int
  , chatStatic     :: Static
  }

staticFiles "static"

mkYesod "Chat" [$parseRoutes|
/          HomeR   GET
/check     CheckR  GET
/post      PostR   GET
/static    StaticR Static chatStatic
|]

instance Yesod Chat where
  approot _ = ""
  defaultLayout content = hamletToContent [$hamlet|
    !!!
    %html
        %head
            %title $pageTitle.content$
            %script!src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"
            %script!src=@StaticR.chat_js@
            ^pageHead.content^
        %body
            ^pageBody.content^
    |]

getHomeR :: Handler Chat RepHtml
getHomeR = do
  Chat clients next _ &lt;- getYesod
  client &lt;- liftIO . atomically $ do
    c &lt;- readTVar next
    writeTVar next (c+1)
    cs &lt;- readTVar clients
    chan  newTChan
              (_,x):_ -&gt; dupTChan x
    writeTVar clients ((c,chan) : cs)
    return c
  applyLayout "Chat Page" mempty [$hamlet|
    !!!
    %h1 Chat Example
    %form
        %textarea!cols=80!rows=20!name=chat
        %p
            %input!type=text!size=15!name=name#name
            %input!type=text!size=60!name=send#send
            %input!type=submit!value=Send
     var clientNumber = $show client$
    |]

getCheckR :: Handler Chat RepJson
getCheckR = do
  liftIO $ putStrLn "Check"
  Chat clients _ _ &lt;- getYesod
  client &lt;- do
    c  invalidArgs ["No client value in Check request"]
      Just c' -&gt; return $ read c'
  cs &lt;- liftIO . atomically $ readTVar clients
  chan  invalidArgs ["Bad client value"]
            Just ch -&gt; return ch
  -- block until there's something there
  first &lt;- liftIO . atomically $ readTChan chan
  let Message s c = first
  jsonToRepJson $ zipJson [&quot;sender&quot;, &quot;content&quot;] [s,c]

zipJson x y = jsonMap $ map (id *** (jsonScalar.string)) $ zip x y

getPostR :: Handler Chat RepJson
getPostR = do
  liftIO $ putStrLn &quot;Post&quot;
  Chat clients _ _ &lt;- getYesod
  (sender,content) &lt;- do
    s &lt;- lookupGetParam &quot;name&quot;
    c  return (s', c')
      _                  -&gt; invalidArgs ["Either name or send not provided."]
  liftIO . atomically $ do
    cs &lt;- readTVar clients
    let chan = snd . head $ cs -- doesn&#039;t matter which one we use, they&#039;re all duplicates
    writeTChan chan (Message sender content)

  jsonToRepJson $ jsonScalar (string &quot;success&quot;)

main :: IO ()
main = do
  clients &lt;- newTVarIO []
  next &lt;- newTVarIO 0
  let static = fileLookupDir &quot;static&quot; typeByExt
  basicHandler 3000 $ Chat clients next static
</pre>
<p>And the JS, which must be called <code>static/chat.js</code> to be loaded properly.</p>
<pre>

$(document).ready(function () {
    $("form").submit(function (e) {
        e.preventDefault();
        $.getJSON("/post", { name: $("#name").attr("value"), send: $("#send").attr("value") }, function(o) { });
        $("#send").attr("value", "");
    });

    checkIn();

});

function checkIn () {
    $.getJSON("/check", { client: clientNumber }, function(o) {
        //alert("response: " + o);
        var ta = $("textarea");
        ta.html(ta.html() + o.sender + ": " + o.content + "\n");
        ta.scrollTop(10000);

        checkIn();
    });
}
</pre>
<br />Filed under: <a href='http://braincrater.wordpress.com/category/1/'>1</a> Tagged: <a href='http://braincrater.wordpress.com/tag/haskell/'>haskell</a>, <a href='http://braincrater.wordpress.com/tag/yesod/'>yesod</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/65/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/65/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/65/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/65/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/65/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/65/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/65/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/65/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=65&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2010/07/22/ajax-chat-app-using-yesod/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>Pimp Your XMonad #4: Urgency Hooks</title>
		<link>http://braincrater.wordpress.com/2009/03/14/pimp-your-xmonad-4-urgency-hooks/</link>
		<comments>http://braincrater.wordpress.com/2009/03/14/pimp-your-xmonad-4-urgency-hooks/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 04:16:34 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[1]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[pimp your xmonad]]></category>
		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=45</guid>
		<description><![CDATA[In a traditional desktop environment such as Gnome or KDE, one has a Windows-style taskbar and tray, with small icons for various apps. When an app wants your attention, it generally changes its tray icon, and might highlight or flash the taskbar entry. In a pure xmonad setup, one typically has neither a taskbar nor [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=45&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In a traditional desktop environment such as Gnome or KDE, one has a Windows-style taskbar and tray, with small icons for various apps. When an app wants your attention, it generally changes its tray icon, and might highlight or flash the taskbar entry. In a pure xmonad setup, one typically has neither a taskbar nor a tray, so how do you know when someone addresses you on IRC, or sends a Pidgin message?</p>
<p>Xmonad offers a solution, the <tt>XMonad.Hooks.UrgencyHook</tt> module. This module offers a variety of ways for xmonad to notify you that an app is requesting your attention, and some ways for you to respond.</p>
<p><b>XMonad Setup</b><br />
When an app sets the X <tt>WM_URGENT</tt> option (see below on how to configure this in some common apps), UrgencyHook will notify you. Precisely how it does so is up to you. One uncommon choice is popping up a temporary dzen2 window, which I won&#8217;t be covering here (see the <tt>XMonad.Hooks.UrgencyHook</tt> <a href="http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Hooks-UrgencyHook.html">docs</a>). By far the most common technique is highlighting the workspace in your dzen or xmobar workspace list.</p>
<p>To start, <tt>import XMonad.Hooks.UrgencyHook</tt>. Then your <tt>xmonad defaultConfig { ... }</tt> line changes to: <tt>xmonad $ withUrgencyHook NoUrgencyHook defaultConfig { ... }</tt>. If you run the darcs version of xmonad and use the <tt>dzen</tt> function or <tt>dzenPP</tt> for your <tt>logHook</tt> you&#8217;re all set! Both of those functions set up dzen to show urgency by highlighting the workspace with the urgent window.</p>
<p>If you use the <tt>xmobar</tt> or <tt>xmobarPP</tt> functions, or want custom colours for your dzen, a little more work is required. You probably have a <tt>logHook</tt> defined, and it probably uses <tt>xmobarPP</tt> or <tt>dzenPP</tt>. If not, see the documentation for <tt>XMonad.Hooks.DynamicLog</tt>, that&#8217;s outside of the scope of this article.</p>
<p>You&#8217;ll have to add the field <tt>ppUrgent = xmobarColor "yellow" "red" . xmobarStrip</tt> to your <tt>xmobarPP</tt> for xmobar, or <tt>ppUrgent = dzenColor "yellow" "red" . dzenStrip</tt> for dzen. Of course, you can choose whatever colours you like.</p>
<p>N.B. The <tt>dzenStrip</tt> and <tt>xmobarStrip</tt> functions only exist in darcs. If you don&#8217;t run darcs xmonad, you can get the code from <a href="http://code.haskell.org/XMonadContrib/XMonad/Hooks/DynamicLog.hs">here</a> and paste it into your <tt>xmonad.hs</tt>.</p>
<p><b>A Handy Keybinding: <tt>focusUrgent</tt></b><br />
<tt>XMonad.Hooks.UrgencyHook</tt> contains a useful keybinding function, <tt>focusUrgent</tt>, which takes no arguments and focuses the most recently urgent window.</p>
<p><b>Configuring Pidgin</b><br />
The second part of setting up UrgencyHook is configuring apps to set <tt>WM_URGENT</tt>. To do this for Pidgin, you need to enable the Message Notificaton plugin (included with Pidgin), and in the plugin configuration tick the &#8220;Set window manager &#8216;URGENT&#8217; hint&#8221; option.</p>
<p><b>Configuring urxvt</b><br />
Another common thing to want highlighting for is when someone uses your name in IRC. To make urxvt set urgent on a bell, add the line <tt>URxvt.urgentOnBell: true</tt> to your <tt>~/.Xdefaults</tt>.</p>
<p>Of course, you&#8217;ll also have to set your IRC client to trigger a bell on highlight (in irssi: <tt>/set bell_beeps ON</tt> and <tt>/set beep_msg_level MSGS NOTICES DCC DCCMSGS HILIGHT</tt>). If you run it in <tt>screen</tt>, make sure <tt>screen</tt> isn&#8217;t set to use visual bell either.</p>
<p>The <tt>XMonad.Hooks.UrgencyHook</tt> <a href="http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Hooks-UrgencyHook.html">docs</a> also have information on setting up these apps and others. If you use a different terminal or IRC client, Google knows how to set it up for urgency hints.</p>
<p><b><tt>UrgencyHook</tt> in Action</b><br />
Here&#8217;s a <a href="http://code.haskell.org/~shepheb/UrgencyHook_screenshot.jpg">screenshot</a> of me hard at work on xmonad, with <tt>UrgencyHook</tt> notifying me that I&#8217;ve received a Pidgin message on workspace <tt>2: IM</tt>. </p>
<p><b>P.S. Twitter</b><br />
I&#8217;m now on <a href="http://twitter.com">Twitter</a> as <a href="http://twitter.com/bradenshep">bradenshep</a>.</p>
<br />Posted in 1 Tagged: haskell, pimp your xmonad, xmonad <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/45/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=45&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2009/03/14/pimp-your-xmonad-4-urgency-hooks/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>Pimp Your XMonad #3: Prompt</title>
		<link>http://braincrater.wordpress.com/2008/11/29/pimp-your-xmonad-3-prompt/</link>
		<comments>http://braincrater.wordpress.com/2008/11/29/pimp-your-xmonad-3-prompt/#comments</comments>
		<pubDate>Sat, 29 Nov 2008 17:57:03 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[1]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[pimp your xmonad]]></category>
		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=42</guid>
		<description><![CDATA[This is a big post that I&#8217;ve been putting off for a long time. There are a lot of awesome modules in the XMonad.Prompt.* family, and so there&#8217;s a lot to cover here. XMonad.Prompt itself defines a library for displaying prompts to the user, with autocompletion and customizable look and feel. This module is a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=42&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is a big post that I&#8217;ve been putting off for a long time. There are a lot of awesome modules in the <tt>XMonad.Prompt.*</tt> family, and so there&#8217;s a lot to cover here.</p>
<p><tt>XMonad.Prompt</tt> itself defines a library for displaying prompts to the user, with autocompletion and customizable look and feel. This module is a back-end library, not intended for use in configurations. What follows is a description and use cases for what I consider the most important modules in the <tt>Prompt</tt> family, a breakdown of how to customize the look and feel, and a quick rundown of the remaining <tt>Prompt</tt> modules as of 0.8.</p>
<p><b>Binding a Prompt action to a key</b><br />
Nearly all <tt>Prompt</tt> actions are performed using key bindings. You can bind them to whichever keys you wish, and they all take the same basic form. First, you need to import the relevant module, for example</p>
<pre>import XMonad.Prompt.Shell</pre>
<p>Second, you need to create a keybinding to call a function from it</p>
<pre>( modMask conf .|. xK_s, shellPrompt myXPConfig )</pre>
<p>or using <tt>XMonad.Util.EZConfig</tt> (which will be the subject of a future PYXM)</p>
<pre>("M-s", shellPrompt myXPConfig)</pre>
<p>The <tt>myXPConfig</tt> argument is how you customize the look and feel of the prompts. See the section called &#8220;Look and Feel Customization&#8221; below on how to do this.</p>
<p><b>Running Commands and Launching Applications: <tt>Shell</tt>, <tt>RunOrRaise</tt>, <tt>DirExec</tt></b><br />
One obvious application of <tt>Prompt</tt> is using it to run shell commands and launch applications. <tt>XMonad.Prompt.Shell.shellPrompt</tt> works similarly to <tt>dmenu</tt>, though it allows command-line arguments to be provided as well, and more complete look-and-feel customization.</p>
<p><tt>XMonad.Prompt.RunOrRaise.runOrRaisePrompt</tt> uses the <tt>XMonad.Actions.RunOrRaise</tt> functionality to prompt for an application, launch it if it isn&#8217;t running, and summon it if it is.</p>
<p><tt>XMonad.Prompt.DirExec.dirExecPrompt</tt> can be used when you want to run programs from a directory not necessarily in your path.</p>
<p><b>Navigating by Window Titles: <tt>Window</tt></b><br />
<tt>XMonad.Prompt.Window</tt>&#8216;s <tt>windowPromptGoto</tt> and <tt>windowPromptBring</tt> functions present an autocompleting list of window titles for all the windows in your session, and either take you to the window you name, or bring it to your location. This can be very helpful both for tracking down windows you&#8217;ve misplaced, and for bringing remote windows here without going to find them.</p>
<p><b>Minimally Disruptive Note-Taking: <tt>AppendFile</tt></b><br />
<tt>XMonad.Prompt.AppendFile</tt> is my personal favourite find from my research for this article. That might not be fair to <tt>Shell</tt> and <tt>Window</tt>, I knew they were there so they weren&#8217;t &#8220;finds&#8221;. What <tt>AppendFile</tt> does is prompt you for one line of text, which it then appends to a file named in your <tt>xmonad.hs</tt>. The intended purpose (there are probably others) is to be able to jot down quick notes by hitting a key binding and typing one line, without disrupting whatever other task you were doing.</p>
<p><b>Arbitrary XMonad Actions: <tt>XMonad</tt></b><br />
<tt>XMonad.Prompt.XMonad</tt> can be viewed as an extension of your key bindings. It displays an autocompleting list of actions, each action bound to an arbitrary X (), like a key binding. You can use the provided default bindings using <tt>xmonadPrompt</tt> (which seem to correspond to roughly the same actions as the default key bindings) or create your own list of (name,action) pairs with <tt>xmonadPromptC</tt>.</p>
<p><b>Look and Feel Customization: <tt>XPConfig</tt></b><br />
The <tt>XPConfig</tt> data type is defined in <tt>XMonad.Prompt</tt>, and it defines the various colours and other parameters that determine the appearance, position, font, size and behaviour of the Prompt box. Following is a rundown of the parameters and what they control.</p>
<ul>
<li><tt>font</tt> &#8212; a <tt>String</tt> naming a font in the X format, eg. <tt>"-*-terminus-*-*-*-*-16-*-*-*-*-*-*-*"</tt> (default: <tt>"-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*"</tt>)</li>
<li><tt>fgColor,bgColor</tt> &#8212; <tt>String</tt>s in <tt>"#rrggbb"</tt> format, defining the fore- and background colours. (defaults: <tt>"#333333"</tt> and <tt>"#FFFFFF"</tt>)</li>
<li><tt>fgHLight,bgHLight</tt> &#8212; <tt>String</tt>s as above, defining the highlight colour for a completion entry. (defaults: <tt>"#000000"</tt> and <tt>"#BBBBBB"</tt>)</li>
<li><tt>borderColor</tt> &#8212; a <tt>String</tt> as above, defining the border colour. (default: <tt>"#FFFFFF"</tt>)</li>
<li><tt>promptBorderWidth</tt> &#8212; the border width in pixels. (default: <tt>1</tt>)</li>
<li><tt>position</tt> &#8212; either <tt>Top</tt> or <tt>Bottom</tt>, the constructors of the <tt>XPPosition</tt> data type. (default: <tt>Bottom</tt>)</li>
<li><tt>height</tt> &#8212; the height of the <tt>Prompt</tt> bar in pixels (make sure it&#8217;s large enough for your font!) (default: <tt>18</tt>)</li>
<li><tt>historySize</tt> &#8212; the number of history entries to save. (default: <tt>256</tt>)</li>
<li><tt>defaultText</tt> &#8212; a <tt>String</tt> defining the text initially in the <tt>Prompt</tt> box when it opens. (default: <tt>""</tt>)</li>
<li><tt>autoComplete</tt> &#8212; a <tt>Maybe Int</tt> that controls the autocompletion behaviour. If <tt>Nothing</tt>, you must press Enter to select the entry. If <tt>Just x</tt>, it will select a unique entry after <tt>x</tt> microseconds. For example, <tt>Just 1000000</tt> would wait 1 full second. (default: <tt>Nothing</tt>)</li>
</ul>
<p><b>Remaining modules</b><br />
These modules are well worth mentioning but are straightforward enough to just list quickly:</p>
<ul>
<li><tt>Workspace</tt> &#8212; takes a <tt>String -&gt; X ()</tt> function and gives it the name of the workspace you specify in the prompt. Could be used to focus the named workspace, bring all the windows on it to the current workspace, or any other action.</li>
<li><tt>Ssh</tt> &#8212; given a host name in the prompt, creates an SSH session in a terminal.</li>
<li><tt>Man</tt> &#8212; displays the man page for the subject you provide in the prompt.</li>
<li><tt>AppLauncher</tt> &#8212; functionality similar to dmenu.</li>
</ul>
<p><b>Conclusion</b><br />
The <tt>XMonad.Prompt.*</tt> family is a prime example of the awesome functionality just waiting to be discovered. Depending on how they use XMonad, I have seen <tt>Ssh</tt>, <tt>Window</tt> and <tt>RunOrRaise</tt> all make an xmonad user&#8217;s day.</p>
<br />Posted in 1 Tagged: haskell, pimp your xmonad, xmonad <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/42/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=42&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/11/29/pimp-your-xmonad-3-prompt/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>Pimp Your XMonad #2: SmartBorders</title>
		<link>http://braincrater.wordpress.com/2008/11/15/pimp-your-xmonad-2-smartborders/</link>
		<comments>http://braincrater.wordpress.com/2008/11/15/pimp-your-xmonad-2-smartborders/#comments</comments>
		<pubDate>Sat, 15 Nov 2008 16:35:06 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[1]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[pimp your xmonad]]></category>
		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=40</guid>
		<description><![CDATA[This is a quick one. The focused window border is sometimes unnecessary, particularly when using Full or Tabbed layouts, since only one window is visible. XMonad.Layout.NoBorders was built to fix this. The simplest option is the noBorders modifier, which will simply never show the border on the layouts it is applied to. It is typically [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=40&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is a quick one. The focused window border is sometimes unnecessary, particularly when using Full or Tabbed layouts, since only one window is visible. <a href="http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Layout-NoBorders.html"><tt>XMonad.Layout.NoBorders</tt></a> was built to fix this.</p>
<p>The simplest option is the <tt>noBorders</tt> modifier, which will simply never show the border on the layouts it is applied to. It is typically applied thus:</p>
<pre>layoutHook = ... ||| noBorders Full ||| ... ||| noBorders Tabbed ||| ...</pre>
<p>Using it on a layout that shows multiple windows, such as Tall, would be a bad idea. But what about Tall with only one window? There is also the <tt>smartBorders</tt> modifier that will hide the borders under either of two conditions:</p>
<ul>
<li>There is only one screen and only one window. (Note that on a Xinerama setup, this will never be true.)</li>
<li>A floating window covers the entire screen (great for mplayer, probably the largest use case)</li>
</ul>
<p>Since smartBorders handles all layouts, even those that can have multiple windows, it is best applied to your whole <tt>layoutHook</tt>:</p>
<pre>layoutHook = avoidStruts $ ... $ smartBorders $ ... ||| tiled ||| ...</pre>
<p><b>Adding to core</b><br />
It has been argued that SmartBorders should be in core, and even be the default behaviour. The main argument against this is that it could be confusing, and that it is rather straightforward to set up. For now, setting up <tt>smartBorders</tt> is easy, and improves the fullscreen video experience.</p>
<br />Posted in 1 Tagged: haskell, pimp your xmonad, xmonad <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/40/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=40&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/11/15/pimp-your-xmonad-2-smartborders/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>Pimp Your XMonad #1: Status bars</title>
		<link>http://braincrater.wordpress.com/2008/11/02/pimp-your-xmonad-1-status-bars/</link>
		<comments>http://braincrater.wordpress.com/2008/11/02/pimp-your-xmonad-1-status-bars/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 00:37:03 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[1]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[pimp your xmonad]]></category>
		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=38</guid>
		<description><![CDATA[I&#8217;ve been hanging around in #xmonad for a long time, and two things have become clear. First, we answer a certain subset of questions many times. Most of the answers are in the FAQ, but the reality is that #xmonad tends to be more efficient, and it gives the answerers a means of procrastination more [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=38&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been hanging around in <tt>#xmonad</tt> for a long time, and two things have become clear. First, we answer a certain subset of questions many times. Most of the answers are in the FAQ, but the reality is that <tt>#xmonad</tt> tends to be more efficient, and it gives the answerers a means of procrastination more useful to society than reading whatever has hit reddit this minute.</p>
<p>Second, some relatively new user whose config is as he wants it will be hanging around in the channel when another new user asks if some feature exists. The first user says &#8220;I never even thought of something like this!&#8221; So I conceived the idea which eventually turned into this series of posts, a place for new users to discover features they never knew they were lacking.</p>
<p><b>Status bars</b></p>
<p>This arguably doesn&#8217;t belong, since it&#8217;s unlikely any user is going to reel in their jaw and say &#8220;I can get it to show me a list of <i>workspaces</i>?!&#8221; Don&#8217;t get me wrong, it&#8217;s an awesome feature, and I would get lost all the time without it, especially on a dual-head setup. But it might not belong since it&#8217;s a relatively easy-to-conceive feature.</p>
<p>Why should you use a status bar? Well, it will list all your currently populated workspaces (meaning those with at least one window on it, as well as those currently visible whether or not they have windows on), which can help with the &#8220;Oh, I forgot I sent this to workspace 8 six hours ago&#8221; problem. Using one of the pretty-printers (available for xmobar and dzen, with customizable behaviour) It highlights the currently focused workspace, as well as the other visible workspaces under a Xinerama setup. Also shown are the current layout, handy to avoid the &#8220;I forgot about these other windows because I was in Full&#8221; problem; and the window title, handy for the subtle jokes of some web comics, and&#8230; well I actually turned that one off.</p>
<p><b>Which status bar app?</b></p>
<p><tt>xmonad</tt> users generally pick one of two: <tt>dzen2</tt> and <tt>xmobar</tt>. The former is a general-purpose Do-It-Yourself status bar program, with sophisticated color and formatting directives that can be inlined in the input. It also supports XFT fonts and XPM icons. However, it is only an engine for displaying the input; you must write a program to generate the necessary input yourself. If that program is <tt>xmonad</tt>, the <tt>logHook</tt> in <tt>xmonad.hs</tt>, and <tt>XMonad.Log.DynamicLog</tt>&#8216;s <tt>dynamicLogWithPP</tt> and <tt>dzenPP</tt> functions make that easy. If you want time, CPU usage, memory usage, etc., you&#8217;ll need to write your own script, with help from the <a href="http://dzen.geekmode.org/dwiki/doku.php">dzen wiki</a>.</p>
<p><tt>xmobar</tt>, as the name hints, was designed for use with <tt>xmonad</tt>. Since <tt>xmonad</tt> doesn&#8217;t have any parts that run periodically, it can&#8217;t output a reliable time, or fresh CPU/memory/disk/network data to any status bar app. <tt>xmobar</tt> handles this itself, allowing the user to specify in a config file what information they want, and in what format it should appear.</p>
<p><b>Setting it up</b></p>
<p>With future articles, I intend to describe in more detail how to set up and get full use out of the features I&#8217;m discussing. In this case, though, the question is so frequently asked and answered in <tt>#xmonad</tt> that I&#8217;m going to punt. Either see <a href="http://haskell.org/haskellwiki/Xmonad/Config_archive/John_Goerzen%27s_Configuration#Installing_xmobar">John Goerzen&#8217;s excellent guide</a> to setting up <tt>xmonad</tt> for its <tt>xmobar</tt> sections, or see that and replace <tt>xmobarPP</tt> with <tt>dzenPP</tt>, and remove the <tt>sTitle</tt> line from the example <tt>xmonad.hs</tt> seen there.</p>
<br />Posted in 1 Tagged: haskell, pimp your xmonad, xmonad <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/38/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/38/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/38/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/38/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/38/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/38/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/38/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/38/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=38&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/11/02/pimp-your-xmonad-1-status-bars/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>xmonad-light 0.8 Released</title>
		<link>http://braincrater.wordpress.com/2008/09/17/xmonad-light-08-released/</link>
		<comments>http://braincrater.wordpress.com/2008/09/17/xmonad-light-08-released/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 14:39:17 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=34</guid>
		<description><![CDATA[Following the recent release of xmonad 0.8, xmonad-light has a 0.8 version out. This version of xmonad-light is built against the xmonad 0.8 release version. The binary (i686) distribution can be downloaded here. New Features As I said in my previous post, I have implemented ManageDocks. Also implemented is defaultKeys, which can be set to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=34&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Following the recent release of xmonad 0.8, xmonad-light has a 0.8 version out. This version of xmonad-light is built against the xmonad 0.8 release version. The binary (i686) distribution can be downloaded <a href="http://code.haskell.org/~shepheb/xmonad-light-0.8.tar.bz2">here</a>.</p>
<p><strong>New Features</strong></p>
<p>As I said in my previous post, I have implemented <tt>ManageDocks</tt>. Also implemented is <tt>defaultKeys</tt>, which can be set to <tt>False</tt> to ignore the default key bindings and define them all yourself.</p>
<p>The <tt>--to-haskell</tt> command-line option will output Haskell code for an <tt>xmonad.hs</tt> equivalent to your <tt>xmonad.conf</tt>.</p>
<p><strong>Binary Distributions</strong></p>
<p>The binary distributions do not require GHC or xmonad to already be installed.</p>
<p>They include a README describing usage and <tt>xmonad.conf</tt> syntax, an INSTALL file, and a TODO with future improvements. I duplicate these below.</p>
<p><strong>Distro Packages</strong></p>
<p>The whole point of xmonad-light is to lower the bar to trying out xmonad by removing the GHC dependency and making it much more lightweight. Anyone looking to package xmonad-light for their distro is invited and encouraged to do so. Comment on this post or email me if you need my support with any part of it.</p>
<p><strong>Future Features</strong></p>
<p>In no particular order:</p>
<ul>
<li>An <tt>xmonad</tt>-like restart system that keeps running with the current configuration on a restart that fails to compile the <tt>xmonad.hs</tt> or parse the <tt>xmonad.conf</tt>.</li>
<li><tt>xmessage</tt> error popups and use of the <tt>~/.xmonad/xmonad.errors</tt> file.</li>
<li><tt>logHook</tt> support, for output to dzen and xmobar.</li>
<li>more layouts and other contrib modules</li>
</ul>
<p>I will be working on all of these, but patches are always welcome.</p>
<p><strong>Bugs</strong></p>
<p>There are almost certainly bugs in xmonad-light. I have been testing it, of course, but I haven&#8217;t really <em>used</em> it. Real use by actual users will, I&#8217;m sure, expose some bugs. Emails to the xmonad mailing list with bugs and feature requests will come to my attention, and I will endeavour to fix them or implement them.</p>
<p><strong>Comments</strong></p>
<p>Any comments, suggestions, gripes, &#8220;it would be nice if&#8221;, or other such are definitely welcome.</p>
<p><strong>Contributing</strong></p>
<p>Throughout this post I say &#8220;me&#8221;. I&#8217;m the sole developer of the xmonad-light project only by circumstance and not by desire. I would welcome any patches, and if you want to hack away on xmonad-light you&#8217;re most welcome. If you think I&#8217;m doing it all wrong, come to #xmonad or the xmonad mailing list and say so!</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/braincrater.wordpress.com/34/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/braincrater.wordpress.com/34/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/34/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/34/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/34/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=34&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/09/17/xmonad-light-08-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>Announcing xmonad-light</title>
		<link>http://braincrater.wordpress.com/2008/08/28/announcing-xmonad-light/</link>
		<comments>http://braincrater.wordpress.com/2008/08/28/announcing-xmonad-light/#comments</comments>
		<pubDate>Thu, 28 Aug 2008 13:50:57 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=27</guid>
		<description><![CDATA[After further work on PlainConfig, and in the light of the impending 0.8 release, it was decided that PlainConfig really doesn&#8217;t belong in xmonad-contrib. No one is going to use PlainConfig from their xmonad.hs, that completely misses the point. Cabal doesn&#8217;t provide an easy parallel to having make for ordinary contrib and make plainconfig for [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=27&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>After further work on <tt>PlainConfig</tt>, and in the light of the impending 0.8 release, it was decided that <tt>PlainConfig</tt> really doesn&#8217;t belong in xmonad-contrib. No one is going to use <tt>PlainConfig</tt> from their <tt>xmonad.hs</tt>, that completely misses the point. Cabal doesn&#8217;t provide an easy parallel to having <tt>make</tt> for ordinary contrib and <tt>make plainconfig</tt> for a <tt>PlainConfig</tt>-ready binary.</p>
<p>Considering all this, it would be far simpler to have the <tt>PlainConfig</tt> functionality as a separate Cabalized project with the binary target, that can be configured using <tt>~/.xmonad/xmonad.conf</tt> and doesn&#8217;t depend on GHC for configuration.</p>
<p>With that, xmonad-light was born. It bears only some resemblance to the <tt>XMonad.Config.PlainConfig</tt> module currently in xmonad-contrib. I had modified it heavily in my local repository before splitting it into xmonad-light, and never pushed it due to the 0.8 release freeze.</p>
<p><b>Misconceptions</b></p>
<p>To be perfectly clear, let me explain a few things xmonad-light is, and is not.</p>
<p>Most importantly, xmonad-light is <i>not</i> a fork of xmonad! It depends on xmonad and xmonad-contrib for building. Rather it is an alternative configuration framework for xmonad, and will be distributed as a binary which has been statically linked to xmonad and xmonad-contrib.</p>
<p>xmonad-light is <i>not</i> a  sign that xmonad has crippled its configuration, or has moved away from Haskell configurations. The goal of xmonad-light is not to replace Haskell configurations, but to provide an alternative with a much more gradual learning curve. The <tt>xmonad.conf</tt> to <tt>xmonad.hs</tt> compiler (see below) makes the transition to a more powerful config easy. This is almost inevitable given the often-seen ramp-up in users&#8217; desire for customization.</p>
<p>xmonad-light <i>is</i> a standalone binary, that <i>does not</i> depend on GHC, xmonad or xmonad-contrib to run on a user&#8217;s machine. It has been statically linked against a version of xmonad and xmonad-contrib, namely whatever version was registered with <tt>ghc-pkg</tt> when xmonad-light was built.</p>
<p>When xmonad-light is executed, it will look for <tt>~/.xmonad/xmonad.hs</tt>. Yes, the Haskell file. If it exists, xmonad-light will try to execute it as xmonad normally does. If this fails (GHC error, GHC doesn&#8217;t exist, xmonad not installed/registered, etc.) or the <tt>xmonad.hs</tt> doesn&#8217;t exist, it then looks for <tt>~/.xmonad/xmonad.conf</tt> and uses that. If neither file exists, it will run the default xmonad config.</p>
<p>When moving to Haskell configuration files, users will need to install xmonad, xmonad-contrib, and GHC normally, as they do now to install and configure xmonad. It will be possible (due to the sequence described above) to mod+q from xmonad-light to normal xmonad.</p>
<p><b>Current Features</b></p>
<p>xmonad-light currently supports everything <tt>PlainConfig</tt> did, which is to say basic configuration of most of the parts of an xmonad.hs. It&#8217;s easier to list the omissions and caveats, which are:</p>
<ul>
<li>Layouts are selected from a predefined list, which currently includes only the standard three.</li>
<li>Any key sequence, including submaps, can be bound using EZConfig syntax, but the actions are selected from a list. This list includes all the actions required to reproduce the defaults, and can <tt>spawn</tt> anything.</li>
<li><tt>ManageHook</tt> conditions are fully expressive, but the actions are selected only from <tt>doIgnore</tt>, <tt>doFloat</tt> and <tt>doShift "workspace"</tt>.</li>
<li>No support for <tt>logHook</tt>s.</li>
<li>No support for <tt>ManageDocks</tt>.</li>
</ul>
<p>The former three are easily expanded to include more layouts and actions as necessary. The latter two are both on my to-do list before releasing a first version of xmonad-light.</p>
<p>The other notable feature is that the compiler from <tt>xmonad.conf</tt> to <tt>xmonad.hs</tt> is complete, and supports all the same features as the main part of xmonad-light. Testing (calling it thorough would be to describe having an umbrella as being prepared for a hurricane) has shown that using the generated xmonad.hs works (ie. <tt>ghc</tt> accepts it) and that the resulting configuration appears to match the <tt>xmonad.conf</tt>. This functionality will be accessed with a command-line option to the xmonad-light binary.</p>
<p><b>Usability and Stability</b></p>
<p>xmonad-light is usabile in the sense that it works, and one could actually use it to configure xmonad without GHC. It is not usable in the sense that there&#8217;s no easy way to get and install it yet. There are no known bugs in the code.</p>
<p>xmonad-light is stable in the sense that the API (the <tt>xmonad.conf</tt> format) is likely to change only by addition of new features. It is unstable in the sense that code and API changes are coming (see below for features I plan to add imminently and in the longer term).</p>
<p><b>To-Do</b></p>
<p>In roughly descending order of priority:</p>
<ul>
<li>Support for <tt>ManageDocks</tt>.</li>
<li>Support for <tt>logHook</tt>s (probably just basic <tt>dzenPP</tt>, <tt>xmobarPP</tt>).</li>
<li>Actually add the <tt>--to-haskell</tt> command-line option.</li>
<li>Release a version guaranteed to work against the 0.8 release of xmonad.</li>
<li>Add more layouts, key actions and <tt>ManageHook</tt> actions as they are desired by users.</li>
</ul>
<p><b>Contributing</b></p>
<p>This has so far been my baby, but I would welcome input (in the form of comments or code) on the design or implementation. The code is available as a darcs repository:</p>
<pre>darcs get http://code.haskell.org/~shepheb/xmonad-light</pre>
<p>The one part of the code that bothers me is the seemingly large amount of duplication, with often nearly identical functions for the XConfig output and the Haskell code output. However, I can&#8217;t see a way to do it more generally.</p>
<p><b>Conclusion</b></p>
<p>I&#8217;m off to add <tt>ManageDocks</tt> support.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/braincrater.wordpress.com/27/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/braincrater.wordpress.com/27/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/27/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/27/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/27/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/27/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/27/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/27/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/27/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/27/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=27&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/08/28/announcing-xmonad-light/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>XMonad for the Masses?</title>
		<link>http://braincrater.wordpress.com/2008/07/26/xmonad-for-the-masses/</link>
		<comments>http://braincrater.wordpress.com/2008/07/26/xmonad-for-the-masses/#comments</comments>
		<pubDate>Sat, 26 Jul 2008 04:44:27 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=24</guid>
		<description><![CDATA[I&#8217;ve been an xmonad user since November, and a contrib developer since December. I love it, and really miss it when I have to use Windows or a friend&#8217;s Linux machine. I&#8217;ve introduced several classmates to it, and the ones who use Linux regularly use xmonad as well. One of the best features of xmonad [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=24&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been an <a href="http://xmonad.org">xmonad</a> user since November, and a contrib developer since December. I love it, and really miss it when I have to use Windows or a friend&#8217;s Linux machine. I&#8217;ve introduced several classmates to it, and the ones who use Linux regularly use xmonad as well.</p>
<p>One of the best features of xmonad is that the configuration file is a Haskell source file. This allows for great extensibility, flexibility and control of one&#8217;s setup.</p>
<p>One of the great weaknesses of xmonad is that the configuration file is a Haskell source file. This means that a user must have a working GHC 6.8 (does 6.6 still work?) installed in order to change their xmonad configuration.</p>
<p>For someone already involved in Haskell, this is not a problem, of course. For someone looking for a good tiling window manager, GHC is a dependency of the heaviest sort. It totals some 150MB of disk on Ubuntu Hardy, for example.</p>
<p>To most people that&#8217;s nothing as far as disk space itself goes; gigabytes of storage are cheap and plentiful, even on laptops. Except for the new breed of EEE PCs and similar! The ritziest models of these have 8GB, most have 4GB. Now GHC is starting to be actually expensive.</p>
<p>Above and beyond the actual disk space cost is the psychological cost of a big dependency. It hardly fits the presentation of xmonad as a minimalist window manager to require the installation a complete compiler toolchain.</p>
<p>There are <a href="http://www.vincentkriek.nl/?p=7">blog posts</a> and mailing list posts about the problem, and a few days ago a user on #xmonad balked at the problem, though the combined weight of Don Stewart, Spencer Janssen and I persuaded him to try it anyway and he seems well pleased with the investment of space.</p>
<p>That last one really drives home the point: GHC is an initial hurdle only; once a user has discovered how awesome xmonad is, they will gladly sacrifice the space for it.</p>
<p>Strictly speaking, xmonad doesn&#8217;t require GHC, you can run GHC&#8217;s binaries without the compiler present. For xmonad, however, this is extremely limiting, as a user cannot even change the mod key without recompiling their xmonad.hs and therefore requiring GHC.</p>
<p>And so we are left with a conundrum. Certainly we do not wish to sacrifice the flexibility and power of using Haskell as a configuration language. So the solution, if any, lies in improving the situation for the user who does not have GHC. Since he current has no options at all, any alternatives are an improvement. I have three ideas for consideration. All are discussed in detail below.</p>
<ol>
<li>An archive of precompiled configuration files alongside the config archive on the wiki.</li>
<li>A web service that could receive an xmonad.hs, compile it, and return the binary for download.</li>
<li>A supplementary plain-text config file, that a precompiled xmonad.hs could parse, generating an <code>XConfig</code> and passing that to the <code>xmonad</code> function.</li>
</ol>
<p><b>1. Config Archive</b><br />
This solution requires the least effort, just a bit of web hosting space. It&#8217;s also the most limiting, since users can&#8217;t mix and match, just select from the existing models. Better than nothing, but not by much. I don&#8217;t have much more to say about it, I support the below ideas more.</p>
<p><b>2. Web Service</b><br />
This solution is the most flexible, allowing users to have their cake and eat it too: the full power of Haskell configurations without the cost of GHC. This would be the approach I would support, except that there are serious challenges here. Template Haskell allows arbitrary execution at compile-time, there&#8217;s an infinite loop in the typechecker. There might be other bugs to allow arbitrary compile-time execution even if we could disable TH. Finally, we need a box to run this on, and no one volunteered.</p>
<p><b>3. <code>PlainConfig</code></b><br />
This option is actually implemented already, at least in proof-of-concept form. I wrote <code>XMonad.Config.PlainConfig</code> in April to demonstrate that this idea could work, and could really run with a precompiled xmonad.hs and without GHC. It works, though of course it is far more limiting than a Haskell configuration. Key bindings are done using <code>EZConfig</code>, and drawing from a list of predefined actions. Layouts are selected from a predefined list as well. Workspaces have arbitrary labels, and as many as you like (though no list comprehensions for the new key bindings!). Mod and NumLock keys can be set freely, as can the colours, border width, terminal and focus-follows-mouse. <code>ManageHook</code>s use a parser from Roman Cheplyaka to handle arbitrary <code>resource</code>, <code>className</code>, and <code>title</code> queries, and the two standard actions <code>doFloat</code> and <code>doIgnore</code>. <code>doShift</code> wasn&#8217;t in core when I wrote <code>PlainConfig</code>, but it is very easy to add.</p>
<p>Similarly, it would be easy to add more layouts and keybinding actions, they are just entries in a <code>Data.Map String Whatever</code>. The two most common configuration elements that are missing are <code>logHook</code>s for status bars and <code>layoutHook</code> modifiers like <code>avoidStruts</code>. The latter is straightforward to add (there are only a few of them, after all), and the former is only slightly more difficult, though it doesn&#8217;t allow a lot of flexibility.</p>
<p><b>The Kicker</b></p>
<p>From the relative volume of those three possiblities, it should be fairly clear which I think is the most practical approach to lightweight xmonad configuration. <code>PlainConfig</code> works, and was designed to be easily extended to add more contrib modules (<code>ManageDocks</code>, <code>EwmhDesktops</code>, layouts), more keybinding actions (<code>CopyWindow</code>, <code>Prompt</code>).</p>
<p>The next key piece of the puzzle is the idea of nightly builds. It&#8217;s been a long time since the 0.7 release, and contrib has been zipping ahead as ever. Not everyone wants to install darcs, check out xmonad, and build xmonad from the darcs source just to get at the new modules and changes. A system of nightly builds would allow these users to stay up-to-date and take advantage of the active development, without needing darcs or indeed, GHC.</p>
<p>It would be straightforward to provide two distinct builds every night. The first would be xmonad as packaged presently for Debian, Arch et al., using the stock config and with no xmonad.hs. Alongside this, however, could be a version which includes the prebuilt xmonad.hs that parses the user&#8217;s xmonad.conf using <code>PlainConfig</code>.</p>
<p><b>And the Gateway Drug</b></p>
<p>Inevitably, many <code>PlainConfig</code> users are going to want something it can&#8217;t provide, and can&#8217;t easily be modified to provide. To avoid making this a dilemma between improved configuration power and having to rewrite their existing config into an xmonad.hs, I plan to write a &#8220;cross-compiler&#8221; from xmonad.conf files to an equivalent xmonad.hs which can be a drop-in replacement.</p>
<p><b>Concerning Evangelism</b></p>
<p>During discussion of the web compilation idea on the mailing list, there was a rather emphatic post cursing the drive in others for evangelising open source projects, since it just invites a load of clueless newbies who were &#8220;attracted to the *marketing* instead of the functionality&#8221;. I certainly try to avoid being a zealot, and readily suggest to users taking exception to fundamental aspects of xmonad that they consider one of the alternative WMs. On the other hand, more users for xmonad means more potential contributors, more people checking bugs, new sources of ideas (whether they can code them personally or not) and more buzz for Haskell. I consider all of these worthy goals, and so if adding a feature like GHC-less configuration to xmonad makes me an evangelist, I will bear that label gladly.</p>
<p>In the spirit of &#8220;patches welcome&#8221;, I plan to work on the &#8220;cross-compiler&#8221; and nightly builds, both normal and <code>PlainConfig</code>-ready, in the next week. I will donate my own desktop to the cause as a build box until an alternative can be found. I hope that once this system is in place, we can manage to put out the word that xmonad doesn&#8217;t require GHC anymore loudly enough to overcome the inertia. Perhaps more importantly, to kill the untruth that one must learn Haskell to use xmonad! There are unfortunately numerous blog posts out there that compare tiling WMs and cite one or both as a disadvantage of xmonad. The latter is particularly insidious, and though xmonad users have said in many places that this was simply not true, that far more users have zero Haskell knowledge than have some, it persists.</p>
<p>Of course, the reverse rumour, that xmonad has crippled their configuration, that Haskell isn&#8217;t a good language for configuration, will need a strong pre-emptive strike. It needs to be blindingly obvious that both options for configuration are still supported!</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/braincrater.wordpress.com/24/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/braincrater.wordpress.com/24/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/24/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/24/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/24/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=24&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/07/26/xmonad-for-the-masses/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>Fixed Point Datatypes</title>
		<link>http://braincrater.wordpress.com/2008/07/07/fixed-point-datatypes/</link>
		<comments>http://braincrater.wordpress.com/2008/07/07/fixed-point-datatypes/#comments</comments>
		<pubDate>Mon, 07 Jul 2008 21:55:00 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[bananas]]></category>
		<category><![CDATA[haskell]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/?p=8</guid>
		<description><![CDATA[This is more Haskell translation of my reading of &#8220;Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire&#8221;, this time concerning fixed points of data types. First, what is a fixed point (aka. fixpoint)? In calculus, functions can have fixed points. These are values such that . As an example, has a fixed point at [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=8&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is more Haskell translation of my reading of &#8220;Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire&#8221;, this time concerning fixed points of data types.</p>
<p>First, what is a fixed point (aka. fixpoint)? In calculus, functions can have fixed points. These are values <img src='http://s0.wp.com/latex.php?latex=x&amp;bg=ffffff&amp;fg=333333&amp;s=0' alt='x' title='x' class='latex' /> such that <img src='http://s0.wp.com/latex.php?latex=f%28x%29+%3D+x&amp;bg=ffffff&amp;fg=333333&amp;s=0' alt='f(x) = x' title='f(x) = x' class='latex' />. As an example, <img src='http://s0.wp.com/latex.php?latex=f%28x%29+%3D+x%5E2&amp;bg=ffffff&amp;fg=333333&amp;s=0' alt='f(x) = x^2' title='f(x) = x^2' class='latex' /> has a fixed point at both 0 and 1. For <img src='http://s0.wp.com/latex.php?latex=f%28x%29+%3D+x&amp;bg=ffffff&amp;fg=333333&amp;s=0' alt='f(x) = x' title='f(x) = x' class='latex' />, every <img src='http://s0.wp.com/latex.php?latex=x&amp;bg=ffffff&amp;fg=333333&amp;s=0' alt='x' title='x' class='latex' /> is a fixpoint!</p>
<p>The notion of fixpoints in programming is somewhat different, though related. In programming fixed points are about self-application, rather than the calculus definition above. I hope the distinction will become clear with some examples.</p>
<p>First, consider the following definition of a simple pair-like type:</p>
<pre>data Pair a b = Pair a b</pre>
<p>I can use any type I like for <tt>a</tt> and <tt>b</tt>, including, say, <tt>Pair a b</tt>:</p>
<pre>example1 = Pair 1 (Pair 2 'a')</pre>
<p>I could go further:</p>
<pre>example2 = Pair 1 (Pair 2 (Pair 3 (Pair 4 (Pair 5 'a'))))</pre>
<p>Is that starting to look familiar? This is an approximation of lists, though not exactly a pleasant one to work with.<br />
Note that <tt>Pair a</tt> is a <tt>Functor</tt>. This idea of applying a <tt>Functor</tt> to itself is exactly fixpoints of data types. With the <tt>Pair a</tt> <tt>Functor</tt>, there is nothing to stop the self-application, so we have something isomorphic to an infinite <tt>[a]</tt>.<br />
Augmenting <tt>Pair</tt> to include a second, nullary, constructor, thus:</p>
<pre>data Pair a b = Stop | Pair a b</pre>
<p>We can then take the fixpoint of the <tt>Functor</tt> <tt>Pair a</tt>, which is isomorphic to:</p>
<pre>data PairFix a = Stop | Pair a (PairFix a)</pre>
<p>And that is clearly isomorphic to desugared lists:</p>
<pre>data List a = Empty | Cons a (List a)</pre>
<p>We can even abstract this notion of self-application of a <tt>Functor</tt> in a curious <tt>newtype</tt>:</p>
<pre>newtype Functor f =&gt; Mu f = In (f (Mu f))</pre>
<p>Such that <tt>PairFix a = Mu (Pair a)</tt>, assuming we&#8217;ve declared an instance of <tt>Functor</tt> for <tt>Pair a</tt>.</p>
<p>Lists are actually only one example. <tt>Mu</tt> can be applied to any <tt>Functor</tt>. Using the binary tree implementation from a <a href="http://braincrater.wordpress.com/2008/04/11/recursion-fail">previous post</a> ,</p>
<pre>data Tree a = Empty | Tree a (Tree a) (Tree a)</pre>
<p>This is the fixpoint of the following type:</p>
<pre>data Cell a b = Empty | Cell a b b</pre>
<p>Since <tt>Cell a</tt> forms a <tt>Functor</tt>, <tt>Mu (Cell a) == Tree a</tt>.</p>
<p>This is all merely an intriguing bit of type theory until we make the realization that all of these structures have something in common. That something is that they can all be recursed over. This can be seen most clearly by looking at lists, which as I demonstrated above are isomorphic to <tt>Mu (Pair a)</tt> using the second definition of <tt>Pair</tt>. The main thrust of <a href="http://wwwhome.cs.utwente.nl/~fokkinga/mmf91m.ps">Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire</a> is that recursion patterns (ie. higher-order functions) we generally think of as being for lists are in fact applicable to any fixpoint data structure.</p>
<p>The paper goes on to describe four core &#8220;foomorphisms&#8221;: catamorphisms, anamorphisms, hylomorphisms and paramorphisms. The names are from Greek, and like &#8220;monad&#8221; and &#8220;functor&#8221; are far scarier than the things they name. These are generalizations of <tt>foldr</tt>, <tt>unfoldr</tt>, primitive recursion and primitive recursion with an accumulating parameter, respectively.</p>
<p>I had originally planned to describe these in more detail here, but Edward Kmett (edwardk) has begun writing a <a href="http://comonad.com/reader/2008/recursion-schemes/">Field Guide</a> to all of these recursion schemes. His posts on each of the foomorphisms include both category theory and concrete examples, and are an excellent read. As you can see from the front page of his Field Guide, there are many, many more than the four described in the original paper. Implementations of all of these and much more are available in <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/category-extras">category-extras</a> on Hackage.</p>
<p>I will still describe some of the core examples and definitions from the paper in later posts. In particular my explorations of the standard examples (Peano numbers, factorial, trees) from Edward Kmett&#8217;s Guide and elsewhere. My goal is to learn to recognize them well &#8220;in the wild&#8221;, since they aid understanding even when the function doesn&#8217;t explicitly use the foomorphism.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/braincrater.wordpress.com/8/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/braincrater.wordpress.com/8/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/8/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=8&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/07/07/fixed-point-datatypes/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
		<item>
		<title>Prototypes Better Than Production</title>
		<link>http://braincrater.wordpress.com/2008/06/04/prototypes-better-than-production/</link>
		<comments>http://braincrater.wordpress.com/2008/06/04/prototypes-better-than-production/#comments</comments>
		<pubDate>Wed, 04 Jun 2008 22:29:00 +0000</pubDate>
		<dc:creator>bradenshep</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[haskell]]></category>

		<guid isPermaLink="false">http://braincrater.wordpress.com/2008/06/04/prototypes-better-than-production/</guid>
		<description><![CDATA[As a take-home technical test as part of a job interview process, I was asked to write a function to convert a number into a string containing its representation in Roman numerals. This is an interesting little puzzle and worth a try, so consider writing or pondering your own solution before reading mine. The precise [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=7&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>As a take-home technical test as part of a job interview process, I was asked to write a function to convert a number into a string containing its representation in Roman numerals. This is an interesting little puzzle and worth a try, so consider writing or pondering your own solution before reading mine.</p>
<p>The precise specification follows:</p>
<ul>
<li>&#8220;M&#8221; = 1000 &#8220;D&#8221; = 500 &#8220;C&#8221; = 100 &#8220;L&#8221; = 50 &#8220;X&#8221; = 10 &#8220;V&#8221; = 5 &#8220;I&#8221; = 1</li>
<li>To find the value of a set of roman numerals you add up the value of the characters.</li>
<li>A power of ten can only be repeated three times i.e., XXX = 30, XXXX is not valid.</li>
<li>Those that are not powers of ten can only appear once, i.e. VV is not valid.</li>
<li>The numbers must read highest-lowest from the left to the right.</li>
<li>If a letter of a smaller value appears before a number of a higher value, then the smaller number is to be subtracted from the higher value. ex: IX = 9.</li>
<li>You can subtract only powers of ten i.e., I, X, C</li>
<li>Only one character can be used to subtract from a larger character. eg IIX = 8 is not allowed.</li>
<li>You can&#8217;t subtract a number from one that is more than 10 times greater. That is, you can only subtract I from V or X, X from L or C, etc. For e.g., IC can not be used for 99. It must be XCIX.</li>
</ul>
<p>I began writing a solution in Java, but then found that the mechanics of writing it in Java were obscuring my thinking about the algorithm. I moved to Haskell to prototype my solution. This proved an effective move, allowing me to stop worrying about whether I&#8217;m using a <tt>String</tt> or <tt>StringBuffer</tt>, and to allow the use of tuples instead of separate classes.</p>
<p>My Haskell solution follows:</p>
<pre>module Main where
import System.IO

-- one element per order of magnitude, with the ones value,
--  and the Roman numeral for 1, 5 and 9 on this order.
romans = [(1000, ("M", "" , ""  ))
         ,(100 , ("C", "D", "CM"))
         ,(10  , ("X", "L", "XC"))
         ,(1   , ("I", "V", "IX"))
         ]

-- utility function for converting at
-- each order of magnitude
multiples 0 _       = ""
multiples 9 (_,_,z) = z
multiples 4 (x,y,_) = x ++ y
multiples 5 (_,y,_) = y
multiples n (x,y,_) | n &gt; 5     = y ++ concat (replicate (n-5) x)
                    | otherwise = concat $ replicate n x

-- the main work: iterate through the orders of
-- magnitude, accumulating the result.
romanize x = fst $ foldl step ("", x) romans

step (r,n) (v,s) = (r ++ multiples d s , m)
    where (d,m) = n `divMod` v 

-- print the (Arabic, Roman) pairs for 1..200
main = mapM_ (print . (\x -&gt; (x , romanize x))) [1..200]</pre>
<p>This solution is based on a left fold, working over a list containing the Roman numeral info for each order of magnitude. In <tt>romans</tt> each list element is a pair containing the order of magnitude (descending order) and a triple with <tt>String</tt>s with the Roman numeral representations of 1, 5, and 9 of that order.</p>
<p>I think the code is probably clearer than a further English description, really. I might be wrong, especially since I wrote it, but I&#8217;m going to stop narrating the code.</p>
<p>So that was my rapid prototyping in Haskell. It took a short time to write, a very short time to debug. It exposed a couple of little mistakes in my initial algorithm, which I corrected quickly. Exactly what rapid prototyping is supposed to give you.</p>
<p>Now comes the curious part. I rewrote the algorithm in Java. The tuples in <tt>romans</tt> became an inner class with those four values as member variables, that&#8217;s fairly natural. It had two member functions essentially implementing <tt>step</tt> and <tt>multiples</tt>. I think the Java code is fairly idiomatic, clear, efficient and generally good. It follows:</p>
<pre>import java.io.*;

public class RomanNumerals {

    // for testing, print out (Arabic, Roman) for 1..200.
    public static void main (String[] args) {
       new RomanNumerals();
    }

    public RomanNumerals () {
        for (int i = 1; i &lt;= 200; i++ ) {
            System.out.println("("+ i + ",\"" + toRoman(i) +"\")");
        }
    }

    // one element per order of magnitude,
    // recording the ones value, and the Roman
    // numeral for multiples of 1, 5 and 9.
    Power[] powers = { new Power (1000, "M", "", ""),
                       new Power (100 , "C", "D", "CM"),
                       new Power (10  , "X", "L", "XC"),
                       new Power (1   , "I", "V", "IX")};
    // 0 &lt; num &lt;= 3999, the maximum by the rules
    // (without a numeral for 5000)
    private String toRoman (int num) {
        StringBuffer buf = new StringBuffer("");
        int power = 0;
        // loop through the orders of magnitude,
        // appending the representation for this order
        // to the running Roman representation.
        while ( num &gt; 0 &amp;&amp; power &lt; powers.length ) {
            buf.append( powers[power].convert(num) );
            num = powers[power].remainder(num);
            power++;
        }

        return buf.toString();
    }

    // container for an order of magnitude, knows how to
    // find the representation given the running number.
    class Power {
        private String one, five, nine;
        private int value;

        public Power (int v, String o, String f, String n) {
            value = v;
            one   = o;
            five  = f;
            nine  = n;
        }

        // calculates the representation for this order
        public String convert (int num){
            num /= value; // truncate
            // now a few special cases
            if ( num == 0 )                return "";
            if ( num == 9 )                return nine;
            if ( num == 4 )                return one + five;
            if ( num == 5 )                return five;

            // handling of 1-3 and 6-8
            String base = "";
            if ( num &gt; 5 ) {
                num -= 5;
                base = five;
            }
            // I could do this in a loop, appending.
            // but this unrolled form is more efficient,
            // and it's only 3 cases.
            switch(num) {
                case 1: return base + one;
                case 2: return base + one + one;
                case 3: return base + one + one + one;
                default: return ""; // can't happen
            }
        }

        // calculates the remainder, the lower-order
        // number left after calculating this order.
        public int remainder (int num){
            return num % value;
        }
    } // class Power
} // class RomanNumerals</pre>
<p>But what did I gain by rewriting it in Java? I only did it because that&#8217;s what the potential employer needs (I&#8217;m sending the Haskell solution too, for fun). Removing that artificial constraint, was there any reason to?</p>
<p>Let&#8217;s compare the two implementations:</p>
<table border="0">
<tbody>
<tr>
<th></th>
<td>Lines</td>
<td>Characters</td>
<td>Binary size (B)</td>
<td>Runtime (s)</td>
</tr>
<tr>
<td>Java</td>
<td>111</td>
<td>2406</td>
<td>1448+1170</td>
<td>0.177</td>
</tr>
<tr>
<td>Haskell (<tt>ghc</tt>)</td>
<td>34</td>
<td>947</td>
<td>434156</td>
<td>0.052</td>
</tr>
<tr>
<td>Haskell (<tt>ghc -O2</tt>)</td>
<td>34</td>
<td>947</td>
<td>393531</td>
<td>0.052</td>
</tr>
</tbody>
</table>
<p>Runtimes are measuring the time required to print from 1 to 200, using <tt>time</tt>.</p>
<p>So by pretty much all of the usual metrics, the Haskell versions are better. They require fewer lines of code, fewer characters, less execution time. Their binaries are considerably heavier, but on the other hand the Java 6 runtime isn&#8217;t being counted here. The same source code will run on any platform supported by Java 6 Standard Edition and GHC respectively, though the Haskell binaries are platform-dependent.</p>
<p>Most vitally, the Haskell version is <em>more</em> type-safe, less likely to cause a runtime exception, is source-portable, executes faster and took less time to write (even though I wrote the Haskell from scratch, and translated into Java!).</p>
<p>The only advantage to the Java version that I can see is that my interviewer reads Java but not Haskell. But I consider that a loss for the company, not for Haskell.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/braincrater.wordpress.com/7/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/braincrater.wordpress.com/7/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/braincrater.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/braincrater.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/braincrater.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/braincrater.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/braincrater.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/braincrater.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/braincrater.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/braincrater.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/braincrater.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/braincrater.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/braincrater.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/braincrater.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/braincrater.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/braincrater.wordpress.com/7/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=braincrater.wordpress.com&amp;blog=4024915&amp;post=7&amp;subd=braincrater&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://braincrater.wordpress.com/2008/06/04/prototypes-better-than-production/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">bradenshep</media:title>
		</media:content>
	</item>
	</channel>
</rss>
