In the meantime, to refocus attention on the original proposal.... ;)<div><br></div><div>For the moment, if only because it&#39;s currently the more standard approach, I&#39;ll concede and use the foldr/build approach.</div>

<div><br></div><div><div>{-# INLINE [0] pairCons #-}</div><div>pairCons :: ((a, b) -&gt; c -&gt; c) -&gt; a -&gt; b -&gt; c -&gt; c</div><div>pairCons = curry</div><div><br></div><div>{-# RULES</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;Data.Map.toAscList-&gt;build&quot; [~1] toAscList = \ m -&gt; GHC.build </div>

<div><span class="Apple-tab-span" style="white-space:pre">                </span>(\ c n -&gt; foldrWithKey (pairCons c) n m);</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>#-}</div></div><div><br></div><div>Since the normal definition of toAscList is just foldrWithKey (curry (:)) [], there&#39;s no need to rewrite it back to toAscList.</div>

<div><br></div><div>A few possible additional modifications:</div><div><ul><li>Pull a similar trick for toDescList.  It&#39;s not as if it&#39;d be all that difficult...</li><li>Reimplement the (==) and compare functions for Data.Map as follows:</li>

</ul><div>m1 == m2 = size m1 == size m2 &amp;&amp; and (zipWith (==) (toAscList m1) (toAscList m2))</div></div><div>m1 `compare` m2 = foldr mappend (compare (size m1) (size m2)) (zipWith compare (toAscList m1) (toAscList m2))</div>

<div><br></div><div>which gets some deforesting.</div><div><br></div><div>Louis Wasserman<br><a href="mailto:wasserman.louis@gmail.com">wasserman.louis@gmail.com</a><br><a href="http://profiles.google.com/wasserman.louis">http://profiles.google.com/wasserman.louis</a><br>

</div>