<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;CEIDQHY-eyp7ImA9WhZQFEw.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622</id><updated>2011-04-21T12:02:51.853-07:00</updated><title>developing an app in Haskell</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/DevelopingAnAppInHaskell" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="developinganappinhaskell" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUYMR3w5eSp7ImA9WxRTEUo.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622.post-4257694727339856494</id><published>2008-08-31T03:00:00.000-07:00</published><updated>2008-08-31T03:06:26.221-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-31T03:06:26.221-07:00</app:edited><title>nzb almost working again</title><content type="html">Developers behind nozbe.com fixed the main issue, so now nzb successfully displays next actions. My suite of functional tests is still failing on adding an action to a specific context though. I have reported that to nozbe.com maintainers and hopefully they can deal with it fast. In the mean time all new actions will end up in an empty context. But all else seems to work fine, so once that problem is fixed nzb will get back to normal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8117871210895255622-4257694727339856494?l=dev-app-in-haskell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/4257694727339856494/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8117871210895255622&amp;postID=4257694727339856494" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/4257694727339856494?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/4257694727339856494?v=2" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/2008/08/nzb-almost-working-again.html" title="nzb almost working again" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A04MQXk-fyp7ImA9WxdaE0k.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622.post-1928175077128834947</id><published>2008-08-21T13:18:00.001-07:00</published><updated>2008-08-21T13:19:40.757-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-21T13:19:40.757-07:00</app:edited><title>nzb broken</title><content type="html">nzb doesn't work for me since yesterday. It is probably due to some change in the api. I will fix it as soon as I find out what is the problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8117871210895255622-1928175077128834947?l=dev-app-in-haskell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/1928175077128834947/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8117871210895255622&amp;postID=1928175077128834947" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/1928175077128834947?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/1928175077128834947?v=2" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/2008/08/nzb-broken.html" title="nzb broken" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CU8HQ3s9fCp7ImA9WxdbE0U.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622.post-6459412078692632380</id><published>2008-08-10T08:55:00.000-07:00</published><updated>2008-08-10T08:57:12.564-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-10T08:57:12.564-07:00</app:edited><title>Haskell refactoring</title><content type="html">&lt;p&gt;
I was doing a "routine patrol" of my Haskell code and found a function with
a TODO note screaming for refactoring. When writing it, I must have thought it
was too verbose expression, but didn't know how to do better at the time. Richer in
Haskell experience I decided to give it a try.

&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
getApiKeyFromNozbe&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;IO&amp;nbsp;(Maybe&amp;nbsp;String)

getApiKeyFromNozbe&amp;nbsp;email&amp;nbsp;password&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;&amp;lt;-&lt;/b&gt;&lt;/font&gt;&amp;nbsp;requestApiKey&amp;nbsp;email&amp;nbsp;password
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/font&gt;&amp;nbsp;response&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;of&lt;/b&gt;&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Just&amp;nbsp;rsp&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/font&gt;&amp;nbsp;jRead&amp;nbsp;rsp&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;of&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#87ceeb"&gt;--TODO shorten&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Nothing)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;return&amp;nbsp;Nothing
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Just&amp;nbsp;apiKey)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;return&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Just&amp;nbsp;apiKey
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;return&amp;nbsp;Nothing

&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;
The function returns an api key or nothing, boxed in IO monad. The code inside the function
uses &lt;tt&gt;requestApiKey&lt;/tt&gt; to get the response from nozbe.com, which happens to be
a JSON description of a map that contains one entry. This entry holds api-key in the value or
null if the credentials provided were not correct.

&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
requestApiKey&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;IO&amp;nbsp;(Maybe&amp;nbsp;String)

&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;
First step is to remove the first &lt;tt&gt;case&lt;/tt&gt; expression, instead of it I use
&lt;tt&gt;&amp;gt;&amp;gt;=&lt;/tt&gt; operator, which is defined in &lt;tt&gt;Monad&lt;/tt&gt; typeclass (&lt;tt&gt;Maybe&lt;/tt&gt; is a &lt;tt&gt;Monad&lt;/tt&gt;). That saves me from specifying what the value should be in case the response is &lt;tt&gt;Nothing&lt;/tt&gt;.

&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
getApiKeyFromNozbe&amp;nbsp;email&amp;nbsp;password&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;do&lt;/b&gt;&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;&amp;lt;-&lt;/b&gt;&lt;/font&gt;&amp;nbsp;requestApiKey&amp;nbsp;email&amp;nbsp;password
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;response&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;&amp;gt;&amp;gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;\&lt;/b&gt;&lt;/font&gt;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/font&gt;&amp;nbsp;jRead&amp;nbsp;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;of&lt;/b&gt;&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Nothing)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Nothing
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Just&amp;nbsp;apiKey)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Just&amp;nbsp;apiKey

&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt; So far so good, one less line. Next I don't like that return at the
beginning of the third line, let's map it.

&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
getApiKeyFromNozbe&amp;nbsp;email&amp;nbsp;password&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(flip&amp;nbsp;fmap)&amp;nbsp;(requestApiKey&amp;nbsp;email&amp;nbsp;password)&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;\&lt;/b&gt;&lt;/font&gt;rsp&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rsp&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;&amp;gt;&amp;gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;\&lt;/b&gt;&lt;/font&gt;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/font&gt;&amp;nbsp;jRead&amp;nbsp;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;of&lt;/b&gt;&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Nothing)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Nothing
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Just&amp;nbsp;apiKey)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Just&amp;nbsp;apiKey

&lt;/font&gt;&lt;/pre&gt;
&lt;p&gt; No fewer lines, but no return now! &lt;tt&gt;response&lt;/tt&gt; renamed to &lt;tt&gt;rsp&lt;/tt&gt;.
Next I don't like that &lt;tt&gt;rsp&lt;/tt&gt; appears twice. Partial operator application to
the rescue.

&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
getApiKeyFromNozbe&amp;nbsp;email&amp;nbsp;password&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(flip&amp;nbsp;fmap)&amp;nbsp;(requestApiKey&amp;nbsp;email&amp;nbsp;password)&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&lt;font color="#f0e68c"&gt;&lt;b&gt;&amp;gt;&amp;gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;\&lt;/b&gt;&lt;/font&gt;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;case&lt;/b&gt;&lt;/font&gt;&amp;nbsp;jRead&amp;nbsp;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;of&lt;/b&gt;&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Nothing)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Nothing
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;Just&amp;nbsp;apiKey)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Just&amp;nbsp;apiKey)

&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt; Let's add a cherry on the top by getting rid of the remaining
&lt;tt&gt;case&lt;/tt&gt; expression. It is obvious that it could return the value of
the entry without checking what it is.

&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
getApiKeyFromNozbe&amp;nbsp;email&amp;nbsp;password&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;
&amp;nbsp;&amp;nbsp;(flip&amp;nbsp;fmap)&amp;nbsp;(requestApiKey&amp;nbsp;email&amp;nbsp;password)&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&lt;font color="#f0e68c"&gt;&lt;b&gt;&amp;gt;&amp;gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;\&lt;/b&gt;&lt;/font&gt;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;let&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;maybeKey)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;jRead&amp;nbsp;txt&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;maybeKey)

&lt;/font&gt;&lt;/pre&gt;
&lt;p&gt;
From 7 to 3 lines, not bad. I wonder how quickly will I understand that code
next time I see it :).

&lt;h4&gt;Bonus&lt;/h4&gt; &lt;p&gt; This is another possible step at minimizing the code.
This one however goes to far I think (I could have trouble understanding it
next time), so I post it only as a bonus. I would consider leaving it, if
something like &lt;tt&gt;dot2&lt;/tt&gt; was in standard library, but I couldn't find anything.

&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
getApiKeyFromNozbe&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;fmap&amp;nbsp;extractKey&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;`dot2`&lt;/b&gt;&lt;/font&gt;&amp;nbsp;requestApiKey&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#bdb76b"&gt;&lt;b&gt;where&lt;/b&gt;&lt;/font&gt;&amp;nbsp;extractKey&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&lt;font color="#f0e68c"&gt;&lt;b&gt;&amp;gt;&amp;gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;\&lt;/b&gt;&lt;/font&gt;t&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;let&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[(&lt;font color="#ffa0a0"&gt;&amp;quot;key&amp;quot;&lt;/font&gt;,&amp;nbsp;k)]&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;jRead&amp;nbsp;t&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;k)

dot2&amp;nbsp;f&amp;nbsp;g&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;\&lt;/b&gt;&lt;/font&gt;x&amp;nbsp;y&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;f&amp;nbsp;(g&amp;nbsp;x&amp;nbsp;y)

&lt;/font&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8117871210895255622-6459412078692632380?l=dev-app-in-haskell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/6459412078692632380/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8117871210895255622&amp;postID=6459412078692632380" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/6459412078692632380?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/6459412078692632380?v=2" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/2008/08/haskell-refactoring.html" title="Haskell refactoring" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEcHR30_eSp7ImA9WxdUF0w.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622.post-275288994527403351</id><published>2008-08-02T14:18:00.000-07:00</published><updated>2008-08-02T14:20:36.341-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-02T14:20:36.341-07:00</app:edited><title>introducing nzb</title><content type="html">&lt;p&gt; The Haskell app I am developing is a command line interface to
nozbe.com. Nozbe.com is a web application implementing Getting Things Done
system. For people who are not familiar with GTD, it is a popular and complete system
of organizing things to be done. My app's name is nzb.

&lt;p&gt; At the moment nzb has less then 500 lines of code, including tests. I
have some unit tests, but they probably give only about 20% coverage. On the
other hand I have many functional tests. I do think that functional tests
are more important than unit tests.

&lt;p&gt; The functional tests run against the real web application, and therefore
are pretty unreliable; one in three runs of the suite something will fail.
Moreover they require an account set up, so anybody wanting to run FTs needs
to create such an account and set it up with data. Everything is in the
build guide, should anyone want to do this.

&lt;p&gt; Currently it lives in &lt;a href='http://code.google.com/p/nzb-cli'&gt;code.google.com/p/nzb-cli&lt;/a&gt;. Someday I might move it to github, which is praised by many.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8117871210895255622-275288994527403351?l=dev-app-in-haskell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/275288994527403351/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8117871210895255622&amp;postID=275288994527403351" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/275288994527403351?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/275288994527403351?v=2" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/2008/08/introducing-nzb.html" title="introducing nzb" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0IGQX4yeCp7ImA9WxZaGE8.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622.post-5221654087923264065</id><published>2008-05-03T07:33:00.000-07:00</published><updated>2008-05-03T07:38:40.090-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-03T07:38:40.090-07:00</app:edited><title>combining functions</title><content type="html">&lt;p&gt;
&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contexts &amp;lt;- getContexts api_key
&lt;font color="#ffdead"&gt;-&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case find (\x -&amp;gt; contextName x == ctx) contexts of&lt;/font&gt;
&lt;font color="#98fb98"&gt;+&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case find ((==ctx) . contextName) contexts of&lt;/font&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Just context -&amp;gt; do
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;let ctx_id = contextID context
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;createAction api_key prj_id ctx_id name
&lt;/font&gt;
&lt;/pre&gt;

&lt;p&gt;
It is better to combine existing functions than define a new one. 
It maybe harder to read to people new to Haskell, but I still like it better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8117871210895255622-5221654087923264065?l=dev-app-in-haskell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/5221654087923264065/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8117871210895255622&amp;postID=5221654087923264065" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/5221654087923264065?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/5221654087923264065?v=2" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/2008/05/combining-functions.html" title="combining functions" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEQBRng-eyp7ImA9WxZbEkQ.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622.post-8920466415818722081</id><published>2008-04-15T13:43:00.001-07:00</published><updated>2008-04-15T13:45:57.653-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-15T13:45:57.653-07:00</app:edited><title>$ operator</title><content type="html">&lt;p&gt; This is hopefully something worth sharing
about Haskell. The &lt;tt&gt;$&lt;/tt&gt; operator.

&lt;p&gt;
&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
 simpleHTTP&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;buildRequest&amp;nbsp;req_text

 simpleHTTP&amp;nbsp;(&amp;nbsp;buildRequest&amp;nbsp;req_text&amp;nbsp;)
&lt;/font&gt;
&lt;/pre&gt;

&lt;p&gt; It is an application operator, it takes a function and an argument,
and ... applies the function to the argument. It's purpose is to save typing
parentheses. It is all about operator precedence.

&lt;p&gt;
&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
 head&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;words&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;config_file_contents

 (&amp;nbsp;head&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;words&amp;nbsp;)&amp;nbsp;config_file_contents
&lt;/font&gt;
&lt;/pre&gt;

&lt;p&gt; Application, &lt;tt&gt;f a&lt;/tt&gt; (&lt;tt&gt;f&lt;/tt&gt; applies to &lt;tt&gt;a&lt;/tt&gt;), binds
stronger than any operator. If it was an operator, think about multiplication operator
which people often omit, it would have precedence set to 10.  &lt;tt&gt;$&lt;/tt&gt;
has precedence set to 0, which is the lowest value of precedence possible.
&lt;p&gt;The &lt;tt&gt;.&lt;/tt&gt; is my another favourite. &lt;tt&gt;(f . g) a == f (g a)&lt;/tt&gt; 
it set to 9, and therefore binds almost as strong as application.
&lt;p&gt;
&lt;pre style="background-color: #333333"&gt;&lt;font face="monospace" color="#ffffff"&gt;
 listActions&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[Action]
 listActions&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;filter&amp;nbsp;notDone&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;map&amp;nbsp;actionFromMap&amp;nbsp;&lt;font color="#f0e68c"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;parseJSON&amp;nbsp;
&lt;/font&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8117871210895255622-8920466415818722081?l=dev-app-in-haskell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/8920466415818722081/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8117871210895255622&amp;postID=8920466415818722081" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/8920466415818722081?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/8920466415818722081?v=2" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/2008/04/operator.html" title="$ operator" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DEANR38_fip7ImA9WxZUEkg.&quot;"><id>tag:blogger.com,1999:blog-8117871210895255622.post-2193900121830628226</id><published>2008-04-03T13:38:00.000-07:00</published><updated>2008-04-03T14:06:36.146-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-03T14:06:36.146-07:00</app:edited><title>Learning Haskell</title><content type="html">&lt;p&gt;
It will be learning by doing. Learning Haskell, a language in which stream 
of Fibonacci numbers can be defined as:

&lt;pre&gt;
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
&lt;/pre&gt;

&lt;p&gt; 
I have chosen Haskell because of &lt;a href='http://web.cecs.pdx.edu/~apt/cs457_2005/hudak-jones.pdf'&gt;compactness&lt;/a&gt; 
and &lt;a href='http://www.math.chalmers.se/~rjmh/Papers/whyfp.html'&gt;composability&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8117871210895255622-2193900121830628226?l=dev-app-in-haskell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://dev-app-in-haskell.blogspot.com/feeds/2193900121830628226/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8117871210895255622&amp;postID=2193900121830628226" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/2193900121830628226?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8117871210895255622/posts/default/2193900121830628226?v=2" /><link rel="alternate" type="text/html" href="http://dev-app-in-haskell.blogspot.com/2008/04/learning-haskell.html" title="Learning Haskell" /><author><name>Kamil Dworakowski</name><uri>http://www.blogger.com/profile/04022605272220857718</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="26" height="32" src="http://bp3.blogger.com/_ht3lkZS1sNs/R1XgH9dpTUI/AAAAAAAAAA4/osn09qfg1LM/S220/ja.jpg" /></author><thr:total>0</thr:total></entry></feed>

