<div dir="ltr"><br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Date: Tue, 23 Sep 2008 09:09:44 -0700<br>
From: &quot;Evan Laforge&quot; &lt;<a href="mailto:qdunkan@gmail.com">qdunkan@gmail.com</a>&gt;<br>
Subject: Re: export toDescList from Data.Map<br>
<br></blockquote><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
&gt; Actually, Data.Map, Data.IntMap, Data.Set and Data.IntSet do not have an<br>
&gt; active maintainer and maybe everybody waits for &quot;GSoC thing for tries&quot;.<br>
&gt;<br>
&gt; Indeed, as you noted yourself &quot;it would be nice to fix up Map, Set,<br>
&gt; IntMap, and IntSet&quot;. I think it is almost mandatory. So would you do<br>
&gt; this, too? &quot;toDescList&quot; makes sense for sets, too. On the other hand, I<br>
&gt; was against toAscList as it is identical to toList. That means I always<br>
&gt; assumed a bias towards &quot;ascending operations&quot;.<br>
<br>
I wouldn&#39;t mind doing some cleanup...</blockquote><div><br>I use Map, Set, IntMap and IntSet very much, and I&#39;m very interested in seeing to it that these important libraries are maintained and improved. However, short of a major API change, like what&#39;s going on with generalized tries and what&#39;s already been done with Edison, I don&#39;t think there is much work left to be done with these libraries at the API level. Just minor changes like the one you&#39;ve proposed. There are some things that could be done though...<br>
<br>&nbsp;- I&#39;m not sure what Benedikt Huber meant by &#39;view&#39;, but I think he means exposing the tree structure, in a read-only way, to users. I think its a shame that the Map/Set libraries do not expose this. The simplest solution would be to have toTree functions that convert it to a Data.Tree, but I don&#39;t think anybody actually likes that data type. A specialized binary tree data type would be more elegant, but there is an issue of how data is stored in the tree. Map/Set store keys and values in internal nodes and use null leaves. IntMap/IntSet store all keys/values in non-null leaves. So maybe this TreeView type would have to be specific to either Map or IntMap. The idea here is that the algorithms and data structures used for these trees are well-known. The papers are linked from the documentation. So the library should expose this to users, in a safe way.<br>
<br>&nbsp;- Since someone raised the issue of test suites for performance and correctness, I think it would also be interesting to investigate what effect the strictness annotations in the tree constructors have on performance. Everyone takes for granted that bangs=faster, but I&#39;ve noticed, as have others, that removing these strictness annotations actually make things run faster. Instead, the tree construction _functions_ should be made strict using seq. The Map construction functions are already strict enough on account of the balancing. Try it for yourself, remove the bangs from the sub-tree fields in the Bin constructor, and run a little benchmark. This would open up the possibility for lazy versions of functions like mapWithKey and mapKeysMonotonic. I had mentioned this previously, but few seemed to care, so I just made the change locally.&nbsp; <a href="http://www.haskell.org/pipermail/libraries/2008-August/010371.html">http://www.haskell.org/pipermail/libraries/2008-August/010371.html</a> . If we we&#39;re going to start a little Map/Set/IntMap/IntSet working group, then I&#39;d like to throw that idea back into the mix. <br>
<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
It&#39;s also galling that IntMap is hardcoded to 32bit ints and writing a<br>
64 bit version would seem to require yet another copy and paste<br>
session. &nbsp;And it seems like theoretically patricia should work on<br>
doubles too. &nbsp;But I&#39;m not sure how to address all this code sharing.<br>
</blockquote><div><br>IntMap is hard coded to Int, which is 32 bits on a 32 bit architecture, and 64 bits on a 64 bit architecture. I think the main reason for this is so that the key can be<br>unpacked/specialized for extra performance, since that is the primary purpose of the library. If you just need sublinear insert/lookup/delete then use a Map. <br>
<br>Are you galled that the key type is not hardcoded to Int64, or that the key is not allowed to be any instance of the Bits class? In the former case, you&#39;d inflate the size of the tree and take a small speed hit on 32bit archs, and in the latter I think you&#39;d have even worse performance. I think the choice of Int is wise because it is the fastest, and that is the point of the library, and if you think about it you&#39;re not going to be dealing with more that 2^32 Ints on a 32 bit computer. (What would they be referencing? Not array positions or file offsets.)&nbsp; If you&#39;re trying to optimize, say, &quot;Map (Int32,Int32) a&quot; into &quot;IntMap64 a&quot;, there are other ways to accomplish that:<br>
<br>import qualified Data.IntMap as IM<br>import Data.IntMap (IntMap)<br><br>newtype IntTrie = IntTrie (IntMap IntTrie) <br><br>empty :: IntTrie<br>empty = IntTrie IM.empty<br><br>insert :: [Int] -&gt; IntTrie -&gt; IntTrie<br>
insert []&nbsp;&nbsp;&nbsp;&nbsp; t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = t<br>insert (x:xs) (IntTrie t) = IntTrie t&#39;<br>&nbsp; where <br>&nbsp; (y,t&#39;) = IM.insertLookupWithKey (const union) x y&#39; t<br>&nbsp; y&#39; = case y of Just y&nbsp; -&gt; insert xs y; Nothing -&gt; insert xs empty<br>
<br>delete :: [Int] -&gt; IntTrie -&gt; IntTrie<br>delete []&nbsp;&nbsp;&nbsp;&nbsp; t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = empty<br>delete (x:xs) (IntTrie t) = IntTrie (IM.update f x t)<br>&nbsp; where<br>&nbsp; f y = case IM.delete x (case delete xs y of IntTrie t -&gt; t) of <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t&#39; | IM.null t&#39; -&gt; Nothing <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | otherwise&nbsp; -&gt; Just (IntTrie t&#39;)<br><br>And so forth. This is an IntSet for arbitrarily long integers represented as [Int]. An IntMap is probably not much more work.<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
&gt; Maybe this explains the little feedback to this ticket, but I would like<br>
&gt; to encourge you, to improve things, anyway.<br>
<br>
Well thanks. &nbsp;It&#39;s nice to hear *something* :)<br>
<br>
</blockquote><div><br>For my $0.02 your proposal is good. toDescList is very important to have in many situations. I&#39;ve had it un-hidden locally for a while now. It&#39;s silly that it wasn&#39;t exported in the first place.<br>
&nbsp;</div>Scott<br></div><br></div>