<div>Background: I participated in this year&#39;s <a href="http://www.icfpcontest.org">ICFP programming contest</a> and our team did quite well, coming in 37th.&nbsp; Our simulator (in&nbsp;somewhat naive C++ with a good algorithm) took about 45 seconds to run the original problem, and afterwards one of my coworkers took the same algorithm and optimized it to run in about 6-10 seconds.
</div>
<div>&nbsp;</div>
<div>The rest of the email will have minor spoilers, so skip it if you want to work on the problem yourself.</div>
<div>&nbsp;</div>
<div>I&#39;m using that problem as a good testcase for learning to write high-performance Haskell.&nbsp; I&#39;m using the same data structure and basic algorithm as the C++ version, but I&#39;m having problems getting the performance where I think it should be.
</div>
<div>&nbsp;</div>
<div>The relevant parts of the code:</div>
<div>&nbsp;</div>
<div><font face="courier new,monospace">&gt; import qualified Data.ByteString.Base as B</font></div>
<div><font face="courier new,monospace">&gt; import qualified Data.ByteString.Char8 as BC</font></div>
<div><font face="courier new,monospace">&gt;</font></div>
<div><font face="courier new,monospace">&gt; type DNABlock = B.ByteString</font></div>
<div><font face="courier new,monospace">&gt; type DNA = [DNABlock]</font></div>
<div>&nbsp;</div>
<div>I represent the DNA string as a simplified <a href="http://en.wikipedia.org/wiki/Rope_(computer_science)">rope</a> that supports fast reading from the front &amp; prepending.</div>
<div>&nbsp;</div>
<div>To access this in a reasonable fashion, I used a view to let me treat the data as a string.&nbsp; Here&#39;s a sample bit of code using that view:</div>
<div>&nbsp;</div>
<div><font face="courier new,monospace">&gt; matchConsts :: Int -&gt; DNA -&gt; (Int, DNA)</font></div>
<div><font face="courier new,monospace">&gt; matchConsts len dna | len `seq` dna `seq` False = undefined -- force strictness</font></div>
<div><font face="courier new,monospace">&gt; matchConsts len dna = case dnaView dna of</font></div>
<div>
<div><font face="courier new,monospace">&gt;&nbsp;&nbsp;&nbsp; (&#39;F&#39;:_) -&gt; matchConsts (len+1) (dropDna 1 dna)</font></div>
<div><font face="courier new,monospace">&gt;&nbsp;&nbsp;&nbsp; (&#39;C&#39;:_) -&gt; matchConsts (len+1) (dropDna 1 dna)</font></div>
<div><font face="courier new,monospace">&gt;&nbsp;&nbsp;&nbsp; (&#39;P&#39;:_) -&gt; matchConsts (len+1) (dropDna 1 dna)</font></div><font face="courier new,monospace">&gt;&nbsp;&nbsp;&nbsp; (&#39;I&#39;:&#39;C&#39;:_) -&gt; matchConsts (len+2) (dropDna&nbsp;2 dna)
</font></div>
<div><font face="courier new,monospace">&gt;&nbsp;&nbsp;&nbsp; _ -&gt; (len, dna)</font></div>
<div>
<div><font face="courier new,monospace"></font>&nbsp;</div>
<div><font face="courier new,monospace">&gt; dropDna :: Int -&gt; DNA -&gt; DNA</font></div></div>
<div><font face="courier new,monospace">&gt; dropDna n dna | n `seq` dna `seq` False = undefined -- force strictness</font></div>
<div><font face="courier new,monospace">&gt; dropDna _ []&nbsp;&nbsp; = []</font></div>
<div><font face="Courier New">&gt; dropDna 0 dna&nbsp; = d</font></div>
<div><font face="courier new,monospace">&gt; dropDna n (d:ds)</font></div>
<div><font face="courier new,monospace">&gt;&nbsp;&nbsp; | n &gt;= BC.length d = dropDna (n - BC.length d) ds</font></div>
<div><font face="Courier New">&gt;&nbsp;&nbsp;&nbsp;| otherwise&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = B.unsafeDrop n d : ds</font></div>
<div><font face="Courier New">&gt; {-# INLINE dropDna #-}</font></div>
<div><font face="courier new,monospace"></font>&nbsp;</div>
<div>Profiling showed that almost all of my time &amp; allocations were spent in my view function:</div>
<div>&nbsp;</div>
<div><font face="courier new,monospace">&gt; dnaView :: DNA -&gt; String</font></div>
<div><font face="courier new,monospace">&gt; -- dnaView d = foldr (++) [] (map BC.unpack d)</font></div>
<div><font face="courier new,monospace">&gt; -- This was ridiculously slow for some reason that I don&#39;t entirely understand</font></div>
<div><font face="courier new,monospace">&gt; dnaView [] = []</font></div>
<div><font face="courier new,monospace">&gt; dnaView (d:ds)</font></div>
<div><font face="courier new,monospace">&gt;&nbsp;&nbsp; | BC.null d = dnaView ds</font></div>
<div><font face="courier new,monospace">&gt;&nbsp;&nbsp; | otherwise = (w2c $ B.unsafeHead d) : dnaView (B.unsafeTail d : ds)</font></div>
<div><font face="Courier New">&gt; {-# INLINE dnaView #-}</font></div>
<div><font face="Courier New"></font>&nbsp;</div>
<div>The question I have for you, the haskell-cafe-reading-audience, is how can I get GHC to do smart code-gen for this?&nbsp; I want&nbsp;&quot;case dnaView dna of ...&quot; to not allocate and instead fuse&nbsp;the list generation with the pattern-match.
</div>
<div>&nbsp;</div>
<div>&nbsp; -- ryan</div>