<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Random Hacks: How to make Data.Set a monad</title>
    <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Technology and Other Fun Stuff</description>
    <item>
      <title>"How to make Data.Set a monad" by Adriaan Moors</title>
      <description>&lt;p&gt;Interesting! &lt;a href="http://scala-lang.org" rel="nofollow"&gt;Scala&lt;/a&gt;&amp;#8217;s support for subtyping,  higher-kinded types (as of 2.5.0, or in a nightly build), and implicit arguments makes it easy to define type classes that abstract over type class contexts (such as Ord a =&amp;gt; in the case of Set as an instance of Monad).&lt;/p&gt;


	&lt;p&gt;A simplified version (without the implicits to fully model type classes) looks like this: (&lt;a href="http://scalasvn.epfl.ch/cgi-bin/viewvc.cgi/scala/trunk/test/files/pos/tcpoly_boundedmonad.scala?view=markup" rel="nofollow"&gt;full source&lt;/a&gt;)&lt;/p&gt;


&lt;pre&gt;
trait Monad[T &amp;lt;: Bound[T], MyType[x &amp;lt;: Bound[x]], Bound[_]] {
  def map[S &amp;lt;: Bound[S]](f: T =&amp;gt; S): MyType[S] 

  def flatMap[S &amp;lt;: RBound[S], RContainer[x &amp;lt;: RBound[x]], RBound[_],  
              Result[x &amp;lt;: RBound[x]] &amp;lt;: Monad[x, RContainer, RBound]]
              (f: T =&amp;gt; Result[S]): Result[S] 

  def filter(p: T =&amp;gt; Boolean): MyType[T]
}

class Set[T &amp;lt;: Ordered[T]] extends Monad[T, Set, Ordered]
&lt;/pre&gt;

Essentially, this says Monad is a type constructor that takes a type T, a type constructor MyType, and a type constructor Bound. More specifically: &lt;ul&gt;
&lt;li&gt;Bound must be of kind * -&amp;gt; *&lt;/li&gt;
&lt;li&gt;T must be of kind * and be a subtype of (Bound T)&lt;/li&gt;
&lt;li&gt;MyType is of kind * -&amp;gt; * and its first argument (call it x) must be a subtype of (Bound x)&lt;/li&gt;
&lt;/ul&gt;

	&lt;p&gt;PS: If you&amp;#8217;d like more details, let me know (adriaan |at| cs/kuleuven/be)&amp;#8212;I&amp;#8217;ve been working on adding support for type constructor polymorphism (as we tend to call higher-kinded types etc.) to the Scala compiler over the past couple of months.&lt;/p&gt;</description>
      <pubDate>Mon, 30 Apr 2007 13:48:09 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:e23568eb-8e1b-452c-83cb-13fb735e35b8</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-422</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by Miles Gould</title>
      <description>&lt;p&gt;Nice one! I ran into the problem of trying to define a monad on a subcategory of the category of types rather than on the whole thing a while back, but couldn&amp;#8217;t get anywhere with it &amp;#8211; nice to see some solutions!&lt;/p&gt;</description>
      <pubDate>Fri, 30 Mar 2007 13:38:07 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:cde02cad-b061-414f-b485-e7a8aa7c5662</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-381</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by Pepe Iborra</title>
      <description>&lt;p&gt;The TH solution is very interesting indeed, since one would probably want to have code using your restricted monad as well as vanilla monads in the same module.&lt;/p&gt;


	&lt;p&gt;In that case, rebinding the do notation via -fnoimplicit-prelude is not an option. Otherwise, you need to keep code that uses a restricted monad in a separate module, which would get annoying very quickly.&lt;/p&gt;</description>
      <pubDate>Sat, 17 Mar 2007 10:08:29 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:39e444af-80a7-4592-90d4-58a3b8054517</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-374</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by Eric</title>
      <description>&lt;p&gt;alpheccar: Note that you don&amp;#8217;t need Template Haskell if you use &lt;code&gt;-fno-implicit-prelude&lt;/code&gt;, as Brandon points out.&lt;/p&gt;


	&lt;p&gt;Still, the Template Haskell solution is definitely interesting in its own right: There are some nice features there, which could be useful for other things.&lt;/p&gt;


	&lt;p&gt;pepe: Oh, that&amp;#8217;s &lt;i&gt;cool&lt;/i&gt;. That might be the right way to get something like this into standard Haskell.&lt;/p&gt;</description>
      <pubDate>Fri, 16 Mar 2007 08:09:36 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:fa97aed7-a95b-491d-b6e2-1d0b389e50aa</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-373</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by pepe Iborra</title>
      <description>&lt;p&gt;Yeah, very cool stuff!
It might be that Associated Types could provide a cleaner solution (see &lt;a href="http://www.haskell.org/pipermail/haskell-cafe/2006-December/020709.html" rel="nofollow"&gt;here&lt;/a&gt;), but this one is &lt;em&gt;good enough&lt;/em&gt; for me.&lt;/p&gt;</description>
      <pubDate>Fri, 16 Mar 2007 04:32:58 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:c319464f-ced1-4273-9e93-4de2777c08e5</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-372</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by alpheccar</title>
      <description>&lt;p&gt;I recently used the &lt;span class="caps"&gt;GADT&lt;/span&gt; method to implement a restricted monad on my blog.&lt;/p&gt;


	&lt;p&gt;But, I prefer the solution with template Haskell. Good idea !&lt;/p&gt;</description>
      <pubDate>Fri, 16 Mar 2007 02:33:07 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:025ab15b-17a6-4060-a055-117628432a10</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-371</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by Eric</title>
      <description>&lt;p&gt;Brandon: Thanks! That&amp;#8217;s really good to know.&lt;/p&gt;


	&lt;p&gt;sigfpe: The Template Haskell bits were actually pretty interesting. I&amp;#8217;ve been meaning to look at Haskell code-generation for a while, and I&amp;#8217;m pleased to discover that things mostly work.&lt;/p&gt;


	&lt;p&gt;There are definitely some missing pieces in the &lt;span class="caps"&gt;API&lt;/span&gt;, though&amp;#8212;not all of Haskell&amp;#8217;s grammar is actually available, and splicing is very limited. So Template Haskell is less powerful than Lisp macros (and it lacks the runtime code-generation support of MetaOCaml). But it&amp;#8217;s still powerful enough to allow for some interesting applications.&lt;/p&gt;</description>
      <pubDate>Fri, 16 Mar 2007 01:29:05 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:fc0c22da-0bc8-48ea-8f95-923add2656e8</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-370</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by sigfpe</title>
      <description>&lt;p&gt;Nice! That looks like it probably needed a lot of persistence to get working.&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s also &lt;a href="http://article.gmane.org/gmane.comp.lang.haskell.cafe/18118" rel="nofollow"&gt;this&lt;/a&gt; which I haven&amp;#8217;t tried yet.&lt;/p&gt;</description>
      <pubDate>Fri, 16 Mar 2007 00:46:02 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:a7ac6e82-3d00-4cf5-9044-49093fe3f110</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-369</link>
    </item>
    <item>
      <title>"How to make Data.Set a monad" by Brandon S Allbery KF8NH</title>
      <description>&lt;p&gt;If you use -fno-implicit-prelude, &lt;span class="caps"&gt;GHC&lt;/span&gt; will use whatever (&amp;gt;&amp;gt;=) is in scope instead of pulling in (Prelude.&amp;gt;&amp;gt;=) behind your back; see section 7.3.5 of the User&amp;#8217;s Guide.&lt;/p&gt;</description>
      <pubDate>Thu, 15 Mar 2007 23:58:49 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:c8968817-bf24-48d9-ad50-939ec686561c</guid>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros#comment-368</link>
    </item>
    <item>
      <title>How to make Data.Set a monad</title>
      <description>&lt;p&gt;&lt;b&gt;&amp;#8230;and how to fake Lisp macros with Template Haskell&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;(I wrote this article in response to &lt;a href="http://www.randomhacks.net/articles/2007/03/05/three-things-i-dont-understand-about-monads#comment-329"&gt;a comment&lt;/a&gt; by
&lt;a href="http://sigfpe.blogspot.com/"&gt;sigfpe&lt;/a&gt;.  You may find it pretty dry reading, unless you want to
build &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language"&gt;domain-specific languages&lt;/a&gt; in Haskell.  Proceed at your own
risk.)&lt;/p&gt;

&lt;p&gt;Haskell&amp;#8217;s built-in &lt;code&gt;Monad&lt;/code&gt; type has some serious limitations.  We can fix those limitations using a number of advanced Haskell techniques, including &lt;a href="http://www.haskell.org/th/"&gt;Template Haskell&lt;/a&gt;, Haskell&amp;#8217;s closest equivalent to Lisp macros.&lt;/p&gt;

&lt;p&gt;We can illustrate the limitations of &lt;code&gt;Monad&lt;/code&gt; with an example from math. In &lt;a href="http://en.wikipedia.org/wiki/Set_theory"&gt;set theory&lt;/a&gt;, we can define a set by specifying how to compute each
element:&lt;/p&gt;

&lt;blockquote&gt;
{ &lt;i&gt;xy&lt;/i&gt; : &lt;i&gt;x&lt;/i&gt; &amp;isin; {1,2,4}, &lt;i&gt;y&lt;/i&gt; &amp;isin; {1,2,4} }
&lt;/blockquote&gt;

&lt;p&gt;We can read this as, &amp;#8220;the set of all &lt;i&gt;xy&lt;/i&gt;, where &lt;i&gt;x&lt;/i&gt;
is one of {1,2,4}, and &lt;i&gt;y&lt;/i&gt; is one of {1,2,4}.&amp;#8221;  To calculate the
answer, we first multiply together all the possible combinations:&lt;/p&gt;

&lt;blockquote&gt;
1&amp;times;1=1, 1&amp;times;2=2, 1&amp;times;4=4, 2&amp;times;1=2, 2&amp;times;2=4, 2&amp;times;4=8, 4&amp;times;1=4, 4&amp;times;2=8, 4&amp;times;4=16
&lt;/blockquote&gt;

&lt;p&gt;We then collect up the answers, and&amp;#8212;because we&amp;#8217;re working with sets&amp;#8211;we
throw away the duplicates:&lt;/p&gt;

&lt;blockquote&gt;
{1,2,4,8,16}
&lt;/blockquote&gt;

&lt;p&gt;Can we do the same thing in Haskell?  Well, using Haskell&amp;#8217;s &lt;a href="http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes"&gt;list
monad&lt;/a&gt;, we can write:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;listExample&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But when we run this, Haskell gives us lots of duplicate values:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;listExample&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;16&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Our problem: We&amp;#8217;re using lists (which can contain duplicate
values) to represent sets (which can&amp;#8217;t).  Can we fix this by switching to
Haskell&amp;#8217;s &lt;code&gt;Data.Set&lt;/code&gt;?&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='varid'&gt;qualified&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Set&lt;/span&gt; &lt;span class='keyword'&gt;as&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;

&lt;span class='comment'&gt;-- This doesn't work.&lt;/span&gt;
&lt;span class='varid'&gt;setExample&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromList&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromList&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, this code fails spectacularly.  A Haskell monad is required
to work for &lt;i&gt;any&lt;/i&gt; types &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;class&lt;/span&gt; &lt;span class='conid'&gt;Monad&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
  &lt;span class='varid'&gt;fail&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But &lt;code&gt;Data.Set&lt;/code&gt; only works for some types.  Specifically, it
requires that values of type &lt;code&gt;a&lt;/code&gt; can be ordered:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Ord&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Set&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varop'&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As it turns out, we can make &lt;code&gt;Data.Set&lt;/code&gt; into a monad.  But be
warned: The solution involves some pretty ugly Haskell abuse.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 15 Mar 2007 22:29:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:93c1c7e1-2355-408f-bf5e-488ce3ea0913</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros</link>
      <category>Haskell</category>
      <category>Monads</category>
      <category>Macros</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/367</trackback:ping>
    </item>
  </channel>
</rss>
