Hmm, is insertWith' new? If I remember right, I think the stack overflows were happening because Map.insertWith isn't strict enough. Otherwise I think the code is the same. But I would expect intTable to be faster, since it uses IntMap, and there's no 
IntMap.insertWith&#39; as of 6.6.1 (though it may be easy enough to add one).<br><br>Chad<br><br><div><span class="gmail_quote">On 10/17/07, <b class="gmail_sendername">Thomas Hartman</b> &lt;<a href="mailto:thomas.hartman@db.com">
thomas.hartman@db.com</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br><font face="sans-serif" size="2">Since I&#39;m interested in the stack overflow
issue, and getting acquainted with quickcheck, I thought I would take this
opportunity to compare your ordTable with some code Yitzchak Gale posted
earlier, against Ham&#39;s original problem.</font>
<br>
<br><font face="sans-serif" size="2">As far as I can tell, they&#39;re the same.
They work on lists up to 100000 element lists of strings, but on 10^6 size
lists I lose patience waiting for them to finish. </font>
<br>
<br><font face="sans-serif" size="2">Is there a more scientific way of figuring
out if one version is better than the other by using, say profiling tools?</font>
<br>
<br><font face="sans-serif" size="2">Or by reasoning about the code?</font>
<br>
<br><font face="sans-serif" size="2">t.</font>
<br>
<br><font face="sans-serif" size="2">****************************************</font>
<br>
<br><font face="Courier New" size="2">import Data.List</font>
<br><font face="Courier New" size="2">import qualified Data.Map as M</font>
<br><font face="Courier New" size="2">import Control.Arrow</font>
<br><font face="Courier New" size="2">import Test.QuickCheck</font>
<br><font face="Courier New" size="2">import Test.GenTestData</font>
<br><font face="Courier New" size="2">import System.Random</font>
<br>
<br><font face="Courier New" size="2">{-</font>
<br><font face="Courier New" size="2">Is there a library function to take
a list of Strings and return a list of</font>
<br><font face="Courier New" size="2">ints showing how many times each String
occurs in the list.</font>
<br>
<br><font face="Courier New" size="2">So for example:</font>
<br>
<br><font face="Courier New" size="2">[&quot;egg&quot;, &quot;egg&quot;,
&quot;cheese&quot;] would return [2,1] </font>
<br><font face="Courier New" size="2">-}</font>
<br>
<br><font face="Courier New" size="2">testYitzGale n = do</font>
<br><font face="Courier New" size="2">&nbsp; l &lt;- rgenBndStrRow (10,10)
(10^n,10^n) &nbsp;-- 100000 strings, strings are 10 chars long, works.
craps out on 10^6.</font>
<br><font face="Courier New" size="2">&nbsp; m &lt;- return $ freqFold l
&nbsp; &nbsp; </font>
<br><font face="Courier New" size="2">&nbsp; putStrLn $ &quot;map items:
&quot; ++ ( show $ M.size m )</font>
<br>
<br><font face="Courier New" size="2">testCScherer n = do</font>
<br><font face="Courier New" size="2">&nbsp; l &lt;- rgenBndStrRow (10,10)
(10^n,10^n) &nbsp;-- same limitations as yitz gale code.</font>
<br><font face="Courier New" size="2">&nbsp; m &lt;- return $ ordTable l
&nbsp; &nbsp; </font>
<br><font face="Courier New" size="2">&nbsp; putStrLn $ &quot;items: &quot;
++ ( show $ length m )</font>
<br>
<br>
<br><font face="Courier New" size="2">-- slow for big lists</font>
<br><font face="Courier New" size="2">--freqArr = Prelude.map ( last &amp;&amp;&amp;
length ) . group . sort</font>
<br>
<br><font face="Courier New" size="2">-- yitz gale code. same as chad scherer
code? it&#39;s simpler to understand, but is it as fast?</font>
<br><font face="Courier New" size="2">freqFold :: [[Char]] -&gt; M.Map [Char]
Int</font>
<br><font face="Courier New" size="2">freqFold = foldl&#39; g M.empty</font>
<br><font face="Courier New" size="2">&nbsp; where g accum x = M.insertWith&#39;
(+) x 1 accum</font>
<br><font face="Courier New" size="2">-- c scherer code. insists on ord.
far as I can tell, same speed as yitz.</font>
<br><font face="Courier New" size="2">ordTable :: (Ord a) =&gt; [a] -&gt;
[(a,Int)]</font>
<br><font face="Courier New" size="2">ordTable xs = M.assocs $! foldl&#39; f
M.empty xs</font>
<br><font face="Courier New" size="2">&nbsp; &nbsp; where f m x = let &nbsp;m&#39;
= M.insertWith (+) x 1 m</font>
<br><font face="Courier New" size="2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Just v = M.lookup x m&#39;</font>
<br><font face="Courier New" size="2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; in v `seq` m&#39;</font>
<br>
<br>
<br><font face="Courier New" size="2">l = [&quot;egg&quot;,&quot;egg&quot;,&quot;cheese&quot;]</font>
<br>
<br><font face="Courier New" size="2">-- other quickcheck stuff</font>
<br><font face="Courier New" size="2">--prop_unchanged_by_reverse = \l -&gt;
( freqArr (l :: [[Char]]) ) == ( freqArr $ reverse l )</font>
<br><font face="Courier New" size="2">--prop_freqArr_eq_freqFold = \l -&gt;
( freqArr (l :: [[Char]]) == (freqFold l))</font>
<br><font face="Courier New" size="2">--test1 = quickCheck prop_unchanged_by_reverse</font>
<br><font face="Courier New" size="2">--test2 = quickCheck prop_freqArr_eq_freqFold</font>
<br>
<br><font face="Courier New" size="2">--------------- generate test data:
</font>
<br><font face="Courier New" size="2">genBndStrRow (minCols,maxCols) (minStrLen,
maxStrLen) = rgen ( genBndLoL (minStrLen, maxStrLen) (minCols,maxCols)
)</font>
<br>
<br><font face="Courier New" size="2">gen gen = do</font>
<br><font face="Courier New" size="2">&nbsp; sg &lt;- newStdGen</font>
<br><font face="Courier New" size="2">&nbsp; return $ generate 10000 sg gen</font>
<br>
<br><font face="Courier New" size="2">-- generator for a list with length
between min and max</font>
<br><font face="Courier New" size="2">genBndList :: Arbitrary a =&gt; (Int,
Int) -&gt; Gen [a]</font>
<br><font face="Courier New" size="2">genBndList (min,max) = do</font>
<br><font face="Courier New" size="2">&nbsp; len &lt;- choose (min,max)</font>
<br><font face="Courier New" size="2">&nbsp; vector len</font>
<br>
<br>
<br><font face="Courier New" size="2">-- lists of lists</font>
<br><font face="Courier New" size="2">--genBndLoL :: (Int, Int) -&gt; (Int,
Int) -&gt; Gen [[a]]</font>
<br><font face="Courier New" size="2">genBndLoL (min1,max1) (min2,max2) =
do</font>
<br><font face="Courier New" size="2">&nbsp; len1 &lt;- choose (min1,max1)</font>
<br><font face="Courier New" size="2">&nbsp; len2 &lt;- choose (min2,max2)</font>
<br><font face="Courier New" size="2">&nbsp; vec2 len1 len2</font>
<br>
<br><font face="Courier New" size="2">--vec2 :: Arbitrary a =&gt; Int -&gt;
Int -&gt; Gen [[a]]</font>
<br><font face="Courier New" size="2">vec2 n m = sequence [ vector m | i
&lt;- [1..n] ]</font>
<br>
<br>
<br>
<br></blockquote></div>