<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Fūzetsu's Corner</title>
    <link href="http://fuuzetsu.co.uk/blog/atom.xml" rel="self" />
    <link href="http://fuuzetsu.co.uk/blog" />
    <id>http://fuuzetsu.co.uk/blog/atom.xml</id>
    <author>
        <name>Mateusz Kowalczyk</name>
        <email>fuuzetsu@fuuzetsu.co.uk</email>
    </author>
    <updated>2018-03-04T22:18:00Z</updated>
    <entry>
    <title>Element-wise vector addition microbenchmarks.</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2018-03-04-Element-wise-vector-addition-microbenchmarks.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2018-03-04-Element-wise-vector-addition-microbenchmarks.html</id>
    <published>2018-03-04T22:18:00Z</published>
    <updated>2018-03-04T22:18:00Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on March  4, 2018
    
        by Fūzetsu
    
</div>

<p>At work we have found a need for a function</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="ot">vsum ::</span> [<span class="dt">Vector</span> <span class="dt">Double</span>] <span class="ot">-&gt;</span> <span class="dt">Vector</span> <span class="dt">Double</span></a></code></pre></div>
<p>This was a fairly hot function so making it fairly quick would be nice. I have at the time written a small benchmark in the project but it was difficult to measure it with everything else that was going on and we only had a limited data set. In benchmarks we use non-empty list of vectors instead (which is always fine with us, removes runtime check and a failure case). There is also an assumptions that all the vectors are uniform length.</p>
<p>Today I finally broke through and decided to just isolate the function and write a benchmark-suite. I have <a href="https://github.com/Fuuzetsu/vector-sum-benchmarks">published the code on GitHub</a>. I don’t plan on putting it on Hackage as it’s not a library nor a useful executable.</p>
<p>What I don’t do in the repository is discuss results that I have gotten. I will be referring to <a href="https://github.com/Fuuzetsu/vector-sum-benchmarks/tree/master/src/Benchmarking/VectorSum">functions defined in the repository</a>. I have copied and pasted them at the bottom of the post for quick reference.</p>
<h2 id="single-vector-many-elements">Single vector, many elements</h2>
<p>The input sample is a single vector with 1 million elements.</p>
<p><a href="#FoldZip">FoldZip</a>, <a href="#RecurseZip">RecurseZip</a>, <a href="#RecurseZipWithN">RecurseZipWithN</a> all perform about the same: after all their job is to simply return the vector.</p>
<p>The ST-family of implementations suffers. It’s pretty easy to guess why. Let’s look at one of the implementations:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb2-1" data-line-number="1">vsum (v <span class="fu">:|</span> vs) <span class="fu">=</span> ST.runST <span class="fu">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb2-2" data-line-number="2">  vec <span class="ot">&lt;-</span> VG.thaw v</a>
<a class="sourceLine" id="cb2-3" data-line-number="3">  <span class="kw">let</span> vlen <span class="fu">=</span> VG.length v</a>
<a class="sourceLine" id="cb2-4" data-line-number="4">  forM_ vs <span class="fu">$</span> \v <span class="ot">-&gt;</span></a>
<a class="sourceLine" id="cb2-5" data-line-number="5">    <span class="kw">let</span> go n <span class="fu">|</span> n <span class="fu">==</span> vlen <span class="fu">=</span> pure ()</a>
<a class="sourceLine" id="cb2-6" data-line-number="6">        go n <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb2-7" data-line-number="7">          VG.unsafeModify vec (<span class="fu">+</span> VG.unsafeIndex v n) n</a>
<a class="sourceLine" id="cb2-8" data-line-number="8">          go (n <span class="fu">+</span> <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb2-9" data-line-number="9">    <span class="kw">in</span> go <span class="dv">0</span></a>
<a class="sourceLine" id="cb2-10" data-line-number="10">  VG.unsafeFreeze vec</a></code></pre></div>
<p>We just <code>thaw</code>ed the vector (resulting in copying) when it was not necessary: in the case of single vector input, we should just yield the vector. I think we could fix this two ways:</p>
<ol type="1">
<li>Add <code>vsum (v :| []) = v</code> case. This will handle the awkward edge case.</li>
<li>Use <a href="https://hackage.haskell.org/package/vector-0.12.0.1/docs/Data-Vector-Generic.html#v:modify">modify</a>. This will only perform a copy of the vector when needed. In this case it won’t be needed, we won’t perform any destructive updates and should be able to get off scot-free with low cost.</li>
</ol>
<p>Let me add both of these ways and let’s compare results. As I’m lazy, I will only add it for the <a href="#UncheckedStFromBack">UncheckedStFromBack</a> variant as I don’t want to add 8 new modules when this is the “superior” version as you will see from the results later.</p>
<pre><code>benchmarking Data.Vector.Unboxed/1x1000000/FoldZip
time                 9.012 ns   (8.963 ns .. 9.072 ns)
                     1.000 R²   (0.999 R² .. 1.000 R²)
mean                 7.168 ns   (6.909 ns .. 7.418 ns)
std dev              785.4 ps   (658.9 ps .. 962.8 ps)
variance introduced by outliers: 93% (severely inflated)

benchmarking Data.Vector.Unboxed/1x1000000/RecurseZip
time                 9.251 ns   (9.203 ns .. 9.317 ns)
                     0.997 R²   (0.994 R² .. 0.999 R²)
mean                 7.325 ns   (7.030 ns .. 7.613 ns)
std dev              785.3 ps   (638.0 ps .. 961.4 ps)
variance introduced by outliers: 93% (severely inflated)

benchmarking Data.Vector.Unboxed/1x1000000/RecurseZipWithN
time                 8.712 ns   (8.554 ns .. 8.997 ns)
                     0.996 R²   (0.990 R² .. 1.000 R²)
mean                 6.846 ns   (6.525 ns .. 7.243 ns)
std dev              964.1 ps   (717.2 ps .. 1.391 ns)
variance introduced by outliers: 96% (severely inflated)

benchmarking Data.Vector.Unboxed/1x1000000/UncheckedStFromBack
time                 514.6 μs   (507.5 μs .. 523.4 μs)
                     0.997 R²   (0.992 R² .. 0.999 R²)
mean                 412.5 μs   (393.9 μs .. 431.3 μs)
std dev              46.70 μs   (37.85 μs .. 58.42 μs)
variance introduced by outliers: 81% (severely inflated)

benchmarking Data.Vector.Unboxed/1x1000000/UncheckedStFromBackModify
time                 1.064 ms   (991.1 μs .. 1.143 ms)
                     0.979 R²   (0.970 R² .. 0.999 R²)
mean                 796.9 μs   (750.5 μs .. 858.1 μs)
std dev              145.4 μs   (104.6 μs .. 192.7 μs)
variance introduced by outliers: 91% (severely inflated)

benchmarking Data.Vector.Unboxed/1x1000000/UncheckedStFromBackBailEmpty
time                 11.01 ns   (10.68 ns .. 11.33 ns)
                     0.990 R²   (0.984 R² .. 0.994 R²)
mean                 9.270 ns   (8.907 ns .. 9.716 ns)
std dev              1.129 ns   (926.8 ps .. 1.456 ns)
variance introduced by outliers: 94% (severely inflated)</code></pre>
<p>Well. <code>modify</code> version was disappointing. It’s even worse than the original by a factor of two. I suppose it shows I don’t understand it and I will need to study what it actually does. Here’s the implementation I chose for it:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb4-1" data-line-number="1">vsum (v0 <span class="fu">:|</span> vs) <span class="fu">=</span> VG.modify (\vec <span class="ot">-&gt;</span> forM_ vs <span class="fu">$</span> \v <span class="ot">-&gt;</span></a>
<a class="sourceLine" id="cb4-2" data-line-number="2">  <span class="kw">let</span> go <span class="dv">0</span> <span class="fu">=</span> pure ()</a>
<a class="sourceLine" id="cb4-3" data-line-number="3">      go n <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb4-4" data-line-number="4">        <span class="kw">let</span> n1 <span class="fu">=</span> n <span class="fu">-</span> <span class="dv">1</span></a>
<a class="sourceLine" id="cb4-5" data-line-number="5">        VG.unsafeModify vec (<span class="fu">+</span> VG.unsafeIndex v n1) n1</a>
<a class="sourceLine" id="cb4-6" data-line-number="6">        go n1</a>
<a class="sourceLine" id="cb4-7" data-line-number="7">  <span class="kw">in</span> go vlen) v0</a>
<a class="sourceLine" id="cb4-8" data-line-number="8">  <span class="kw">where</span></a>
<a class="sourceLine" id="cb4-9" data-line-number="9">    vlen <span class="fu">=</span> VG.length v0</a></code></pre></div>
<p>The good news is that bailing out on empty tail helps a lot and the check only takes extra 2ns. I think it’s worth it if the alternative is paying 500µs on a hit. It of course depends on the use-case: if you’re the only consumer of the function and you know you’ll always have multiple vectors, maybe you want to save the 2ns.</p>
<p>If you’re interested in the numbers, see the <a href="../misc/vector_sum_report_1x1000000.html">html report</a> for this case or the <a href="../misc/vector_sum_report_1x1000000.txt">textual output</a>.</p>
<h2 id="many-vectors-single-element">Many vectors, single element</h2>
<p>The input sample is 1 million vectors with a single element each.</p>
<p>Some weirdness starts here: <a href="#RecurseZipWithN">RecurseZipWithN</a> is the fastest by far for boxed vectors. It is however by far the slowest for storable and unboxed vectors.</p>
<p>I wonder if the size of the function is hindering some optimisations. Let’s add a new variant: one that still does zipWith6 but if there is not enough work left, it folds over the rest of the input.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb5-1" data-line-number="1">vsum (v0 <span class="fu">:|</span> v1 <span class="fu">:</span> v2 <span class="fu">:</span> v3 <span class="fu">:</span> v4 <span class="fu">:</span> v5 <span class="fu">:</span> vs) <span class="fu">=</span></a>
<a class="sourceLine" id="cb5-2" data-line-number="2">  vsum (VG.zipWith6 (\e0 e1 e2 e3 e4 e5 <span class="ot">-&gt;</span> e0 <span class="fu">+</span> e1 <span class="fu">+</span> e2 <span class="fu">+</span> e3 <span class="fu">+</span> e4 <span class="fu">+</span> e5) v0 v1 v2 v3 v4 v5 <span class="fu">:|</span> vs)</a>
<a class="sourceLine" id="cb5-3" data-line-number="3">vsum (v0 <span class="fu">:|</span> vs) <span class="fu">=</span> foldl&#39; (VG.zipWith (<span class="fu">+</span>)) v0 vs</a></code></pre></div>
<p>Slightly better for boxed case and even worse for storable and unboxed cases. We could try with <code>zipWith3</code> but I suspect it would not help much.</p>
<p>The <code>UncheckedStFromBackBailEmpty</code> variant from previous section actually performs even better than the original though only marginally. The <code>modify</code> variant is comparable to the original so that’s hopeful at least. The ST variants are by far the fastest for this case with bail empty being the best but not by a lot. All are acceptable.</p>
<p>If you’re interested in the numbers, see the <a href="../misc/vector_sum_report_1000000x1.html">html report</a> for this case or the <a href="../misc/vector_sum_report_1000000x1.txt">textual output</a>.</p>
<h2 id="many-vectors-many-elements">Many vectors, many elements</h2>
<p>The input sample is 5000 vectors with 5000 elements and the results are pretty much the same as for the previous case. Or so I would have wanted to say but then:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb6-1" data-line-number="1">benchmarking <span class="dt">Data.Vector.Unboxed</span><span class="fu">/</span>5000x5000<span class="fu">/</span><span class="dt">UncheckedStFromBackModify</span></a>
<a class="sourceLine" id="cb6-2" data-line-number="2">time                 <span class="fl">23.68</span> ms   (<span class="fl">23.60</span> ms <span class="fu">..</span> <span class="fl">23.76</span> ms)</a>
<a class="sourceLine" id="cb6-3" data-line-number="3">                     <span class="fl">1.000</span> <span class="dt">R</span>²   (<span class="fl">1.000</span> <span class="dt">R</span>² <span class="fu">..</span> <span class="fl">1.000</span> <span class="dt">R</span>²)</a>
<a class="sourceLine" id="cb6-4" data-line-number="4">vector<span class="fu">-</span>sum<span class="fu">-</span>benchmarks<span class="fu">-</span>bench<span class="fu">:</span> <span class="fu">./</span><span class="dt">Data</span><span class="fu">/</span><span class="dt">Vector</span><span class="fu">/</span>Generic.hs<span class="fu">:</span><span class="dv">245</span> ((<span class="fu">!</span>))<span class="fu">:</span> index out <span class="kw">of</span> bounds (<span class="fu">-</span><span class="dv">9223372036854775808</span>,<span class="dv">1000</span>)</a>
<a class="sourceLine" id="cb6-5" data-line-number="5"><span class="dt">CallStack</span> (from <span class="dt">HasCallStack</span>)<span class="fu">:</span></a>
<a class="sourceLine" id="cb6-6" data-line-number="6">  error, called at <span class="fu">./</span><span class="dt">Data</span><span class="fu">/</span><span class="dt">Vector</span><span class="fu">/</span><span class="dt">Internal</span><span class="fu">/</span>Check.hs<span class="fu">:</span><span class="dv">87</span><span class="fu">:</span><span class="dv">5</span> <span class="kw">in</span> vector<span class="fu">-</span><span class="fl">0.12</span><span class="fu">.</span><span class="fl">0.1</span><span class="fu">-</span><span class="dt">JlawpRjIcMJIYPJVsWriIA</span><span class="fu">:</span><span class="dt">Data.Vector.Internal.Check</span></a>
<a class="sourceLine" id="cb6-7" data-line-number="7">vector<span class="fu">-</span>sum<span class="fu">-</span>benchmarks<span class="fu">-</span>bench<span class="fu">:</span> thread blocked indefinitely <span class="kw">in</span> an <span class="dt">MVar</span> operation</a>
<a class="sourceLine" id="cb6-8" data-line-number="8"><span class="dt">Benchmark</span> vector<span class="fu">-</span>sum<span class="fu">-</span>benchmarks<span class="fu">-</span>bench<span class="fu">:</span> <span class="dt">ERROR</span></a></code></pre></div>
<p>Interesting. I don’t want to sit through another minutes long run (boxed vectors take 7 seconds per iteration on 5000x5000 compared to 20ms for unboxed and 50ms for storable) so let’s drop down to 1000x1000. I definitely will have to keep that crash in mind. I wonder why it crashed there and not in Storable or boxed. Very bizarre. I’m actually guessing it might a bug in criterion considering the weird index (overflow?) and that it came up half way through its printing. Actually that seems to be exactly it: <a href="https://github.com/bos/criterion/issues/162">here</a>’s the (fixed) criterion issue. Fixed two months ago at that. I guess <a href="https://github.com/bos/criterion/issues/188">I can ask</a>. I could update criterion through stack.yaml but I don’t want to invalidate previous results in middle of the experiment. Let’s go to 1000x1000.</p>
<p>The results are very similar to many vectors, single element case, just scaled differently. <code>zipWithN</code> solutions are still the fastest for boxed vectors (factor of 2x better over others) and just completely awful for storable and unboxed (factor of 20-30x worse compared to others).</p>
<p>If you’re interested in the numbers, see the <a href="../misc/vector_sum_report_1000x1000.html">html report</a> for this case or the <a href="../misc/vector_sum_report_1000x1000.txt">textual output</a>.</p>
<h2 id="vectors-200-elements">200 vectors, 200 elements</h2>
<p>Out of curiousity I also ran with a smaller data set of 200x200. With this amount of data the zipWithN versions are actually worse even for boxed vectors. The usual ST bail empty version is the fastest: well, on par with <a href="#UncheckedStFromFront">UncheckedStFromFront</a> which seems to have taken the lead but only within a small margin. It seems that there’s a point for unboxed vectors where <code>zipWithN</code> functions stop being the worst and become the best. Perhaps it’s all the other functions that degrade with larger inputs.</p>
<p>For unboxed and storable vectors the story is the usual: ST variants win with unchecked ST from back versions coming out on top.</p>
<p>If you’re interested in the numbers, see the <a href="../misc/vector_sum_report_200x200.html">html report</a> for this case or the <a href="../misc/vector_sum_report_200x200.txt">textual output</a>.</p>
<h2 id="general-remarks">General remarks</h2>
<p>Comments with regards to the overall process</p>
<h3 id="data-generation">Data generation</h3>
<p>The data generation is nothing exotic:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="co">-- | Creates data suitable for various vsum implementations.</span></a>
<a class="sourceLine" id="cb7-2" data-line-number="2">createData</a>
<a class="sourceLine" id="cb7-3" data-line-number="3"><span class="ot">  ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb7-4" data-line-number="4">  <span class="ot">=&gt;</span> <span class="dt">Int</span> <span class="co">-- ^ Number of vectors</span></a>
<a class="sourceLine" id="cb7-5" data-line-number="5">  <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="co">-- ^ Length of vectors</span></a>
<a class="sourceLine" id="cb7-6" data-line-number="6">  <span class="ot">-&gt;</span> <span class="dt">NonEmpty</span> (v (<span class="dt">Double</span>))</a>
<a class="sourceLine" id="cb7-7" data-line-number="7">createData vs l <span class="fu">=</span> Data.List.NonEmpty.fromList <span class="fu">$</span></a>
<a class="sourceLine" id="cb7-8" data-line-number="8">  Prelude.map (VG.generate l <span class="fu">.</span> mult) [<span class="dv">1</span> <span class="fu">..</span> vs]</a>
<a class="sourceLine" id="cb7-9" data-line-number="9">  <span class="kw">where</span></a>
<a class="sourceLine" id="cb7-10" data-line-number="10"><span class="ot">    mult ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Double</span></a>
<a class="sourceLine" id="cb7-11" data-line-number="11">    mult x y <span class="fu">=</span> fromIntegral (x <span class="fu">*</span> y)</a></code></pre></div>
<p>As we’re using criterion (and <code>weigh</code> for allocations), this is evaluated to normal form before being passed into the benchmark.</p>
<h3 id="number-gathering">Number gathering</h3>
<p>It would take too long to run full set of benchmarks every time I wanted to make a change. I have started with the functions listed below in the appendix as the baseline and only ran the full set of criterion benchmarks once. The number of benchmark cases that run is <code>3 * length sizes * length vsumFunctions</code>. This number can grow fairly fast and especially boxed vector benchmarks take a long time.</p>
<p>Therefore once I had a base, I had re-ran benchmarks for the cases I was interested in for this blog post. These are the numbers you see above. You can see the original full-run numbers if you wish: <a href="../misc/vector_sum_report_full.txt">text version</a> and (WARNING: this report is rather large and will potentially hang your browser. It’s not very useful to look at either because every time is on the same diagram and boxed vector operations for large inputs completely dwarf the rest making it useless as visual aid) <a href="../misc/vector_sum_report_full.html">html version</a>. You’ll note that the ST functions to deal with singleton cases are missing as well as zipWith6 variant of zipWithN: these functions were introduced during this blog post.</p>
<h3 id="memory-usage">Memory usage</h3>
<p>There are also allocation numbers available. These are in full as they only need to run a single iteration per case. You can see them <a href="../misc/vector_sum_report_full_alloc.txt">here</a>. The numbers are fairly uniform. <code>zipWithN</code> cases seem to have a little less live data sticking around but pay in significant increase in number of garbage collections. All other differences between the allocation numbers are fairly negligible.</p>
<h3 id="contrived-test-cases">Contrived test cases</h3>
<p>We’re benchmarking the speed of the functions on their own. They do not live with other code and don’t benefit from any optimisations one might get if they were inlined into real codebase. As always, take these numbers with a grain of salt. They are at best like-for-like comparisons. In real code performance may change due to fusion &amp;c. Write benchmarks for your application before changing your code based on microbenchmarks here (or anywhere).</p>
<h3 id="different-vector-types">Different vector types</h3>
<p>Boxed vectors seem to behave very differently performance-wise compared to storable and unboxed vectors. It’s unclear to me as to why. Of course I expect them to be much slower but it makes me curious why they don’t scale in the same way as the other vector types. Why are the ST functions worse than zipWithN variants for larger input data for boxed vectors? This may be an investigation for another day.</p>
<h3 id="specialisation-and-inlining">Specialisation and inlining</h3>
<p>I had to explicitly specialise the functions otherwise GHC worked on the unspecialised generic versions and the results were quite a lot different. This is a standard practice anyway so remember to do it in your code too. Remember to add INLINABLE too as SPECIALISE pragmas turn off inlining by default. In real code, we may instead benefit from INLINE over SPECIALISE. For more information on these things <a href="https://www.stackbuilders.com/tutorials/haskell/ghc-optimization-and-fusion/">check out this excellent post on GHC optimisation and fusion</a>.</p>
<h3 id="st-traversal-from-the-back-and-from-the-front">ST traversal from the back and from the front</h3>
<p>Some of the ST functions presented have two variants: one that traverses vectors from the back and one from the front. The reason why I’m measuring both is that it does seem to make a noticable difference with traversal from the back usually winning slightly. I have tried this because I was told fairly recently that checking if something is zero can be faster than comparing to another number as there are special instructions to do that. I do not know if that’s what’s happening or if it is true but it seems faster.</p>
<h3 id="non-exhaustive-examples">Non-exhaustive examples</h3>
<p>There are multiple other ways we could write <code>vsum</code>. A simple example is instead of using explicit indexing into vector traversals in ST, just use <code>imapM_</code>. If I remember correctly this one optimises to the same loop as forward traversals but of course you’re relying on optimisations. It would be very good to add more cases. Another example is aforementioned <code>zipWithN</code> for N other than 3. You never know. Mixing existing examples is also possible: we can mix bail empty and <code>modify</code>: we always bail on empty tail (so we don’t pay the price of pointless modify which we found out to be quite bad) but we may receive benefits of <code>modify</code> in common case, if there are any.</p>
<p>Additions encouraged and most welcome.</p>
<h3 id="hmatrix-repa-accelerate-parallel">hmatrix, repa, accelerate, parallel, …</h3>
<p>None of the fancy parallel libraries were used. Not even the not fancy ones. Mostly because I was lazy but in big part because those usually only play nicely together in certain scenarios. In benchmarks on real codebase, <code>vsum</code> we had there was faster only up to the point at which <code>hmatrix</code> started winning out for rather large vectors. I want to avoid poorly benchmarking these libraries where data conversions &amp;c. would completely skew the data. Often the rest of your program already deals in those formats.</p>
<h3 id="rts-hardware">RTS, hardware</h3>
<p>No fancy RTS flags were passed, only -N. This means parallel GC was on &amp;c. Everything was on fair ground however so that’s fine.</p>
<p>The numbers presented here were ran on i7 6770k, 64GB rig, NixOS rig.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The general winner has emerged and it is</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb8-2" data-line-number="2">vsum (v0 <span class="fu">:|</span> []) <span class="fu">=</span> v0</a>
<a class="sourceLine" id="cb8-3" data-line-number="3">vsum (v0 <span class="fu">:|</span> vs) <span class="fu">=</span> ST.runST <span class="fu">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb8-4" data-line-number="4">  vec <span class="ot">&lt;-</span> VG.thaw v0</a>
<a class="sourceLine" id="cb8-5" data-line-number="5">  <span class="kw">let</span> vlen <span class="fu">=</span> VG.length v0</a>
<a class="sourceLine" id="cb8-6" data-line-number="6">  forM_ vs <span class="fu">$</span> \v <span class="ot">-&gt;</span></a>
<a class="sourceLine" id="cb8-7" data-line-number="7">    <span class="kw">let</span> go <span class="dv">0</span> <span class="fu">=</span> pure ()</a>
<a class="sourceLine" id="cb8-8" data-line-number="8">        go n <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb8-9" data-line-number="9">          <span class="kw">let</span> n1 <span class="fu">=</span> n <span class="fu">-</span> <span class="dv">1</span></a>
<a class="sourceLine" id="cb8-10" data-line-number="10">          VG.unsafeModify vec (<span class="fu">+</span> VG.unsafeIndex v n1) n1</a>
<a class="sourceLine" id="cb8-11" data-line-number="11">          go n1</a>
<a class="sourceLine" id="cb8-12" data-line-number="12">    <span class="kw">in</span> go vlen</a>
<a class="sourceLine" id="cb8-13" data-line-number="13">  VG.unsafeFreeze vec</a></code></pre></div>
<p>This performed very marginally worse for the unusual case of a single vector (2ns loss). It actually performed very marginally better than the unchecked cases on other inputs. Rarely some other ST function would match it or come very slightly ahead: the differences can easily be dismissed as noise in measurements. Note this function is quite unsafe and will do awful, horrible things if any of the vectors is smaller than the first one. This assumption is OK for our use-case and can be easily statically verified. If this was to be a library function, more care should be taken. At the very least use <code>!</code> for indexing instead and crash the application rather than leaking memory contents to an attacker.</p>
<p>For boxed vectors, zipWithN versions were on top after a certain amount of data. If you’re using those vectors, be wary. You shouldn’t be using them for numerical data usually anyway.</p>
<p>I would definitely like to understand why zipWithN versions are so badly performing as well as why we see such a discrepancy in patterns for boxed vectors.</p>
<p>I would also like to confirm the back/front traversal speed reasons. If there’s interest I might do it in another post. It might just be the case of peeking into the generated ASM. I would also like to repeat the experiments with LLVM as well as play with different compilation flags to both GHC and LLVM.</p>
<h2 id="appendix-functions-used-in-the-benchmarking">Appendix: Functions used in the benchmarking</h2>
<h3 id="fold-zip">Fold zip<a name="FoldZip"></a></h3>
<div class="sourceCode" id="cb9"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="co">-- | Fold a (+) zip with first vector as inital value.</span></a>
<a class="sourceLine" id="cb9-2" data-line-number="2"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb9-3" data-line-number="3">vsum (v <span class="fu">:|</span> vs) <span class="fu">=</span> foldl&#39; (VG.zipWith (<span class="fu">+</span>)) v vs</a>
<a class="sourceLine" id="cb9-4" data-line-number="4"><span class="ot">{-# INLINABLE vsum #-}</span></a>
<a class="sourceLine" id="cb9-5" data-line-number="5"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (V.Vector Double) -&gt; V.Vector Double #-}</span></a>
<a class="sourceLine" id="cb9-6" data-line-number="6"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VS.Vector Double) -&gt; VS.Vector Double #-}</span></a>
<a class="sourceLine" id="cb9-7" data-line-number="7"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VU.Vector Double) -&gt; VU.Vector Double #-}</span></a></code></pre></div>
<p>This is a straight forward zip going vector by vector.</p>
<h3 id="recurse-zip">Recurse zip<a name="RecurseZip"></a></h3>
<div class="sourceCode" id="cb10"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb10-1" data-line-number="1"><span class="co">-- | Similar to FoldZip but use explicit recursion for the zips.</span></a>
<a class="sourceLine" id="cb10-2" data-line-number="2"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb10-3" data-line-number="3">vsum (v <span class="fu">:|</span> v1 <span class="fu">:</span> vs) <span class="fu">=</span> vsum (VG.zipWith (<span class="fu">+</span>) v v1 <span class="fu">:|</span> vs)</a>
<a class="sourceLine" id="cb10-4" data-line-number="4">vsum (v <span class="fu">:|</span> []) <span class="fu">=</span> v</a>
<a class="sourceLine" id="cb10-5" data-line-number="5"><span class="ot">{-# INLINABLE vsum #-}</span></a>
<a class="sourceLine" id="cb10-6" data-line-number="6"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (V.Vector Double) -&gt; V.Vector Double #-}</span></a>
<a class="sourceLine" id="cb10-7" data-line-number="7"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VS.Vector Double) -&gt; VS.Vector Double #-}</span></a>
<a class="sourceLine" id="cb10-8" data-line-number="8"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VU.Vector Double) -&gt; VU.Vector Double #-}</span></a></code></pre></div>
<h3 id="recurse-zipwithn">Recurse zipWithN<a name="RecurseZipWithN"></a></h3>
<div class="sourceCode" id="cb11"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="co">-- | Matches on up to 6 vectors and uses zipWithN to consume as many</span></a>
<a class="sourceLine" id="cb11-2" data-line-number="2"><span class="co">-- of the as we can.</span></a>
<a class="sourceLine" id="cb11-3" data-line-number="3"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb11-4" data-line-number="4">vsum (v0 <span class="fu">:|</span> v1 <span class="fu">:</span> v2 <span class="fu">:</span> v3 <span class="fu">:</span> v4 <span class="fu">:</span> v5 <span class="fu">:</span> vs) <span class="fu">=</span></a>
<a class="sourceLine" id="cb11-5" data-line-number="5">  vsum (VG.zipWith6 (\e0 e1 e2 e3 e4 e5 <span class="ot">-&gt;</span> e0 <span class="fu">+</span> e1 <span class="fu">+</span> e2 <span class="fu">+</span> e3 <span class="fu">+</span> e4 <span class="fu">+</span> e5) v0 v1 v2 v3 v4 v5 <span class="fu">:|</span> vs)</a>
<a class="sourceLine" id="cb11-6" data-line-number="6">vsum (v0 <span class="fu">:|</span> v1 <span class="fu">:</span> v2 <span class="fu">:</span> v3 <span class="fu">:</span> v4 <span class="fu">:</span> vs) <span class="fu">=</span></a>
<a class="sourceLine" id="cb11-7" data-line-number="7">  vsum (VG.zipWith5 (\e0 e1 e2 e3 e4 <span class="ot">-&gt;</span> e0 <span class="fu">+</span> e1 <span class="fu">+</span> e2 <span class="fu">+</span> e3 <span class="fu">+</span> e4) v0 v1 v2 v3 v4 <span class="fu">:|</span> vs)</a>
<a class="sourceLine" id="cb11-8" data-line-number="8">vsum (v0 <span class="fu">:|</span> v1 <span class="fu">:</span> v2 <span class="fu">:</span> v3 <span class="fu">:</span> vs) <span class="fu">=</span></a>
<a class="sourceLine" id="cb11-9" data-line-number="9">  vsum (VG.zipWith4 (\e0 e1 e2 e3 <span class="ot">-&gt;</span> e0 <span class="fu">+</span> e1 <span class="fu">+</span> e2 <span class="fu">+</span> e3) v0 v1 v2 v3 <span class="fu">:|</span> vs)</a>
<a class="sourceLine" id="cb11-10" data-line-number="10">vsum (v0 <span class="fu">:|</span> v1 <span class="fu">:</span> v2 <span class="fu">:</span> vs) <span class="fu">=</span></a>
<a class="sourceLine" id="cb11-11" data-line-number="11">  vsum (VG.zipWith3 (\e0 e1 e2 <span class="ot">-&gt;</span> e0 <span class="fu">+</span> e1 <span class="fu">+</span> e2) v0 v1 v2 <span class="fu">:|</span> vs)</a>
<a class="sourceLine" id="cb11-12" data-line-number="12">vsum (v0 <span class="fu">:|</span> v1 <span class="fu">:</span> vs) <span class="fu">=</span></a>
<a class="sourceLine" id="cb11-13" data-line-number="13">  vsum (VG.zipWith (<span class="fu">+</span>) v0 v1 <span class="fu">:|</span> vs)</a>
<a class="sourceLine" id="cb11-14" data-line-number="14">vsum (v0 <span class="fu">:|</span> []) <span class="fu">=</span> v0</a>
<a class="sourceLine" id="cb11-15" data-line-number="15"><span class="ot">{-# INLINABLE vsum #-}</span></a>
<a class="sourceLine" id="cb11-16" data-line-number="16"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (V.Vector Double) -&gt; V.Vector Double #-}</span></a>
<a class="sourceLine" id="cb11-17" data-line-number="17"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VS.Vector Double) -&gt; VS.Vector Double #-}</span></a>
<a class="sourceLine" id="cb11-18" data-line-number="18"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VU.Vector Double) -&gt; VU.Vector Double #-}</span></a></code></pre></div>
<p>This is a recursive implementation using up to zipWith6 (as that’s the highest defined in the vector library).</p>
<h3 id="checked-st-from-back">Checked ST from back<a name="CheckedStFromBack"></a></h3>
<div class="sourceCode" id="cb12"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb12-1" data-line-number="1"><span class="co">-- | Go through vectors one by one and mutate an accumulating vector</span></a>
<a class="sourceLine" id="cb12-2" data-line-number="2"><span class="co">-- in place. Uses checked operation for indexing of non-initial vector.</span></a>
<a class="sourceLine" id="cb12-3" data-line-number="3"><span class="co">-- Vectors are traversed from the back.</span></a>
<a class="sourceLine" id="cb12-4" data-line-number="4"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb12-5" data-line-number="5">vsum (v <span class="fu">:|</span> vs) <span class="fu">=</span> ST.runST <span class="fu">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb12-6" data-line-number="6">  vec <span class="ot">&lt;-</span> VG.thaw v</a>
<a class="sourceLine" id="cb12-7" data-line-number="7">  <span class="kw">let</span> vlen <span class="fu">=</span> VG.length v</a>
<a class="sourceLine" id="cb12-8" data-line-number="8">  forM_ vs <span class="fu">$</span> \v <span class="ot">-&gt;</span></a>
<a class="sourceLine" id="cb12-9" data-line-number="9">    <span class="kw">let</span> go <span class="dv">0</span> <span class="fu">=</span> pure ()</a>
<a class="sourceLine" id="cb12-10" data-line-number="10">        go n <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb12-11" data-line-number="11">          <span class="kw">let</span> n1 <span class="fu">=</span> n <span class="fu">-</span> <span class="dv">1</span></a>
<a class="sourceLine" id="cb12-12" data-line-number="12">          VG.unsafeModify vec (<span class="fu">+</span> v <span class="fu">VG.!</span> n1) n1</a>
<a class="sourceLine" id="cb12-13" data-line-number="13">          go n1</a>
<a class="sourceLine" id="cb12-14" data-line-number="14">    <span class="kw">in</span> go vlen</a>
<a class="sourceLine" id="cb12-15" data-line-number="15">  VG.unsafeFreeze vec</a>
<a class="sourceLine" id="cb12-16" data-line-number="16"><span class="ot">{-# INLINABLE vsum #-}</span></a>
<a class="sourceLine" id="cb12-17" data-line-number="17"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (V.Vector Double) -&gt; V.Vector Double #-}</span></a>
<a class="sourceLine" id="cb12-18" data-line-number="18"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VS.Vector Double) -&gt; VS.Vector Double #-}</span></a>
<a class="sourceLine" id="cb12-19" data-line-number="19"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VU.Vector Double) -&gt; VU.Vector Double #-}</span></a></code></pre></div>
<h3 id="checked-st-from-front">Checked ST from front<a name="CheckedStFromFront"></a></h3>
<div class="sourceCode" id="cb13"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb13-1" data-line-number="1"><span class="co">-- | Go through vectors one by one and mutate an accumulating vector</span></a>
<a class="sourceLine" id="cb13-2" data-line-number="2"><span class="co">-- in place. Uses checked operation for indexing of non-initial vector.</span></a>
<a class="sourceLine" id="cb13-3" data-line-number="3"><span class="co">-- Vectors are traversed from the front.</span></a>
<a class="sourceLine" id="cb13-4" data-line-number="4"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb13-5" data-line-number="5">vsum (v <span class="fu">:|</span> vs) <span class="fu">=</span> ST.runST <span class="fu">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb13-6" data-line-number="6">  vec <span class="ot">&lt;-</span> VG.thaw v</a>
<a class="sourceLine" id="cb13-7" data-line-number="7">  <span class="kw">let</span> vlen <span class="fu">=</span> VG.length v</a>
<a class="sourceLine" id="cb13-8" data-line-number="8">  forM_ vs <span class="fu">$</span> \v <span class="ot">-&gt;</span></a>
<a class="sourceLine" id="cb13-9" data-line-number="9">    <span class="kw">let</span> go n <span class="fu">|</span> n <span class="fu">==</span> vlen <span class="fu">=</span> pure ()</a>
<a class="sourceLine" id="cb13-10" data-line-number="10">        go n <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb13-11" data-line-number="11">          VG.unsafeModify vec (<span class="fu">+</span> v <span class="fu">VG.!</span> n) n</a>
<a class="sourceLine" id="cb13-12" data-line-number="12">          go (n <span class="fu">+</span> <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb13-13" data-line-number="13">    <span class="kw">in</span> go <span class="dv">0</span></a>
<a class="sourceLine" id="cb13-14" data-line-number="14">  VG.unsafeFreeze vec</a>
<a class="sourceLine" id="cb13-15" data-line-number="15"><span class="ot">{-# INLINABLE vsum #-}</span></a>
<a class="sourceLine" id="cb13-16" data-line-number="16"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (V.Vector Double) -&gt; V.Vector Double #-}</span></a>
<a class="sourceLine" id="cb13-17" data-line-number="17"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VS.Vector Double) -&gt; VS.Vector Double #-}</span></a>
<a class="sourceLine" id="cb13-18" data-line-number="18"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VU.Vector Double) -&gt; VU.Vector Double #-}</span></a></code></pre></div>
<h3 id="unchecked-st-from-back-security-vulnerability-edition">Unchecked ST from back (security vulnerability edition)<a name="UncheckedStFromBack"></a></h3>
<div class="sourceCode" id="cb14"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb14-1" data-line-number="1"><span class="co">-- | Go through vectors one by one and mutate an accumulating vector</span></a>
<a class="sourceLine" id="cb14-2" data-line-number="2"><span class="co">-- in place. Uses unsafe operations, performs no bounds checks.</span></a>
<a class="sourceLine" id="cb14-3" data-line-number="3"><span class="co">-- Vectors are traversed from the back.</span></a>
<a class="sourceLine" id="cb14-4" data-line-number="4"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb14-5" data-line-number="5">vsum (v <span class="fu">:|</span> vs) <span class="fu">=</span> ST.runST <span class="fu">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb14-6" data-line-number="6">  vec <span class="ot">&lt;-</span> VG.thaw v</a>
<a class="sourceLine" id="cb14-7" data-line-number="7">  <span class="kw">let</span> vlen <span class="fu">=</span> VG.length v</a>
<a class="sourceLine" id="cb14-8" data-line-number="8">  forM_ vs <span class="fu">$</span> \v <span class="ot">-&gt;</span></a>
<a class="sourceLine" id="cb14-9" data-line-number="9">    <span class="kw">let</span> go <span class="dv">0</span> <span class="fu">=</span> pure ()</a>
<a class="sourceLine" id="cb14-10" data-line-number="10">        go n <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb14-11" data-line-number="11">          <span class="kw">let</span> n1 <span class="fu">=</span> n <span class="fu">-</span> <span class="dv">1</span></a>
<a class="sourceLine" id="cb14-12" data-line-number="12">          VG.unsafeModify vec (<span class="fu">+</span> VG.unsafeIndex v n1) n1</a>
<a class="sourceLine" id="cb14-13" data-line-number="13">          go n1</a>
<a class="sourceLine" id="cb14-14" data-line-number="14">    <span class="kw">in</span> go vlen</a>
<a class="sourceLine" id="cb14-15" data-line-number="15">  VG.unsafeFreeze vec</a>
<a class="sourceLine" id="cb14-16" data-line-number="16"><span class="ot">{-# INLINABLE vsum #-}</span></a>
<a class="sourceLine" id="cb14-17" data-line-number="17"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (V.Vector Double) -&gt; V.Vector Double #-}</span></a>
<a class="sourceLine" id="cb14-18" data-line-number="18"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VS.Vector Double) -&gt; VS.Vector Double #-}</span></a>
<a class="sourceLine" id="cb14-19" data-line-number="19"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VU.Vector Double) -&gt; VU.Vector Double #-}</span></a></code></pre></div>
<h3 id="unchecked-st-from-front-security-vulnerability-edition">Unchecked ST from front (security vulnerability edition)<a name="UncheckedStFromFront"></a></h3>
<div class="sourceCode" id="cb15"><pre class="sourceCode hs"><code class="sourceCode haskell"><a class="sourceLine" id="cb15-1" data-line-number="1"><span class="co">-- | Go through vectors one by one and mutate an accumulating vector</span></a>
<a class="sourceLine" id="cb15-2" data-line-number="2"><span class="co">-- in place. Uses unsafe operations, performs no bounds checks.</span></a>
<a class="sourceLine" id="cb15-3" data-line-number="3"><span class="co">-- Vectors are traversed from the front.</span></a>
<a class="sourceLine" id="cb15-4" data-line-number="4"><span class="ot">vsum ::</span> <span class="dt">VG.Vector</span> v <span class="dt">Double</span> <span class="ot">=&gt;</span> <span class="dt">NonEmpty</span> (v <span class="dt">Double</span>) <span class="ot">-&gt;</span> v <span class="dt">Double</span></a>
<a class="sourceLine" id="cb15-5" data-line-number="5">vsum (v <span class="fu">:|</span> vs) <span class="fu">=</span> ST.runST <span class="fu">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb15-6" data-line-number="6">  vec <span class="ot">&lt;-</span> VG.thaw v</a>
<a class="sourceLine" id="cb15-7" data-line-number="7">  <span class="kw">let</span> vlen <span class="fu">=</span> VG.length v</a>
<a class="sourceLine" id="cb15-8" data-line-number="8">  forM_ vs <span class="fu">$</span> \v <span class="ot">-&gt;</span></a>
<a class="sourceLine" id="cb15-9" data-line-number="9">    <span class="kw">let</span> go n <span class="fu">|</span> n <span class="fu">==</span> vlen <span class="fu">=</span> pure ()</a>
<a class="sourceLine" id="cb15-10" data-line-number="10">        go n <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb15-11" data-line-number="11">          VG.unsafeModify vec (<span class="fu">+</span> VG.unsafeIndex v n) n</a>
<a class="sourceLine" id="cb15-12" data-line-number="12">          go (n <span class="fu">+</span> <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb15-13" data-line-number="13">    <span class="kw">in</span> go <span class="dv">0</span></a>
<a class="sourceLine" id="cb15-14" data-line-number="14">  VG.unsafeFreeze vec</a>
<a class="sourceLine" id="cb15-15" data-line-number="15"><span class="ot">{-# INLINABLE vsum #-}</span></a>
<a class="sourceLine" id="cb15-16" data-line-number="16"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (V.Vector Double) -&gt; V.Vector Double #-}</span></a>
<a class="sourceLine" id="cb15-17" data-line-number="17"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VS.Vector Double) -&gt; VS.Vector Double #-}</span></a>
<a class="sourceLine" id="cb15-18" data-line-number="18"><span class="ot">{-# SPECIALISE vsum :: NonEmpty (VU.Vector Double) -&gt; VU.Vector Double #-}</span></a></code></pre></div>
]]></summary>
</entry>
<entry>
    <title>Trying out GHC compact regions for improved latency (Pusher case study).</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2018-03-03-GHC-compact-regions-for-improved-latency.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2018-03-03-GHC-compact-regions-for-improved-latency.html</id>
    <published>2018-03-03T00:00:00Z</published>
    <updated>2018-03-03T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on March  3, 2018
    
        by Fūzetsu
    
</div>

<p>(I have rambled yesterday about <code>.Internal</code> modules in libraries and why you should use them but I messed up the RSS feed: if you haven’t seen the post but are a library author, you might want to check it out <a href="http://fuuzetsu.co.uk/blog/posts/2018-03-02-A-case-for-Internal-modules.html">here</a>.)</p>
<p>A couple of years ago, <a href="https://making.pusher.com/latency-working-set-ghc-gc-pick-two/">Pusher published a quite good blog post</a> about how GHC garbage collection time pauses scale with size of the working set. I will not re-iterate the blog post, you should go read it.</p>
<p>Ultimately in the post the authors <a href="https://stackoverflow.com/questions/36772017/reducing-garbage-collection-pause-time-in-a-haskell-program/36779227">went to StackOverflow</a> for help/confirmation of their findings.</p>
<p>What was of particular interest to me is that the accepted answer mentions an up-coming feature called compact regions which could help. As it happens, today’s the future and the feature has been in GHC since 8.2.x. Very roughly, it allows you to put data in a contiguous memory region with some restrictions. One of these restrictions is that this data can not have outgoing pointers. This is very useful because if it has no outgoing pointers then we know it’s not holding onto any GC roots and doesn’t have to be traversed or copied by the GC. I very highly recommend that you <a href="http://ezyang.com/compact.html">read the paper</a>: I was certainly very impressed. I also didn’t know the original use-case was to send unserialised data over network and GC latency seems a bit more secondary. There are more cool things you can do like write the region out to disk and read it back later which can potentially save you a lot of time that you might have had to spend on (de)serialisation: very inefficient if you’re running the binary multiple times.</p>
<p>Let’s try using compact regions for Pusher’s use-case and check if it can help. This is an exploratory exercise for me, it could fail horribly and I will be discovering things as we go along.</p>
<h2 id="replicating-reported-results">Replicating reported results</h2>
<p>Pusher’s reduced code was as follows.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">module</span> <span class="dt">Main</span> (main) <span class="kw">where</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"></a>
<a class="sourceLine" id="cb1-3" data-line-number="3"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Exception</span> <span class="kw">as</span> <span class="dt">Exception</span></a>
<a class="sourceLine" id="cb1-4" data-line-number="4"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Monad</span> <span class="kw">as</span> <span class="dt">Monad</span></a>
<a class="sourceLine" id="cb1-5" data-line-number="5"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">ByteString</span></a>
<a class="sourceLine" id="cb1-6" data-line-number="6"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map.Strict</span> <span class="kw">as</span> <span class="dt">Map</span></a>
<a class="sourceLine" id="cb1-7" data-line-number="7"></a>
<a class="sourceLine" id="cb1-8" data-line-number="8"><span class="kw">data</span> <span class="dt">Msg</span> <span class="fu">=</span> <span class="dt">Msg</span> <span class="fu">!</span><span class="dt">Int</span> <span class="fu">!</span><span class="dt">ByteString</span><span class="fu">.</span><span class="dt">ByteString</span></a>
<a class="sourceLine" id="cb1-9" data-line-number="9"></a>
<a class="sourceLine" id="cb1-10" data-line-number="10"><span class="kw">type</span> <span class="dt">Chan</span> <span class="fu">=</span> <span class="dt">Map.Map</span> <span class="dt">Int</span> <span class="dt">ByteString</span><span class="fu">.</span><span class="dt">ByteString</span></a>
<a class="sourceLine" id="cb1-11" data-line-number="11"></a>
<a class="sourceLine" id="cb1-12" data-line-number="12"><span class="ot">message ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Msg</span></a>
<a class="sourceLine" id="cb1-13" data-line-number="13">message n <span class="fu">=</span> <span class="dt">Msg</span> n (<span class="dt">ByteString</span><span class="fu">.</span>replicate <span class="dv">1024</span> (fromIntegral n))</a>
<a class="sourceLine" id="cb1-14" data-line-number="14"></a>
<a class="sourceLine" id="cb1-15" data-line-number="15"><span class="ot">pushMsg ::</span> <span class="dt">Chan</span> <span class="ot">-&gt;</span> <span class="dt">Msg</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">Chan</span></a>
<a class="sourceLine" id="cb1-16" data-line-number="16">pushMsg chan (<span class="dt">Msg</span> msgId msgContent) <span class="fu">=</span></a>
<a class="sourceLine" id="cb1-17" data-line-number="17">  Exception.evaluate <span class="fu">$</span></a>
<a class="sourceLine" id="cb1-18" data-line-number="18">    <span class="kw">let</span></a>
<a class="sourceLine" id="cb1-19" data-line-number="19">      inserted <span class="fu">=</span> Map.insert msgId msgContent chan</a>
<a class="sourceLine" id="cb1-20" data-line-number="20">    <span class="kw">in</span></a>
<a class="sourceLine" id="cb1-21" data-line-number="21">      <span class="kw">if</span> <span class="dv">200000</span> <span class="fu">&lt;</span> Map.size inserted</a>
<a class="sourceLine" id="cb1-22" data-line-number="22">      <span class="kw">then</span> Map.deleteMin inserted</a>
<a class="sourceLine" id="cb1-23" data-line-number="23">      <span class="kw">else</span> inserted</a>
<a class="sourceLine" id="cb1-24" data-line-number="24"></a>
<a class="sourceLine" id="cb1-25" data-line-number="25"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb1-26" data-line-number="26">main <span class="fu">=</span> <span class="dt">Monad</span><span class="fu">.</span>foldM_ pushMsg Map.empty (map message [<span class="dv">1</span><span class="fu">..</span><span class="dv">1000000</span>])</a></code></pre></div>
<p>On my machine this gives me the following numbers:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" data-line-number="1">[<span class="ex">nix-shell</span>:/tmp]$ ghc -O2 -optc-O3 -fforce-recomp Main.hs <span class="kw">&amp;&amp;</span> <span class="ex">./Main</span> +RTS -s</a>
<a class="sourceLine" id="cb2-2" data-line-number="2">[<span class="ex">1</span> of 1] Compiling Main             ( Main.hs, Main.o )</a>
<a class="sourceLine" id="cb2-3" data-line-number="3"><span class="ex">Linking</span> Main ...</a>
<a class="sourceLine" id="cb2-4" data-line-number="4">   <span class="ex">2</span>,996,460,128 bytes allocated in the heap</a>
<a class="sourceLine" id="cb2-5" data-line-number="5">     <span class="ex">365</span>,809,560 bytes copied during GC</a>
<a class="sourceLine" id="cb2-6" data-line-number="6">     <span class="ex">235</span>,234,760 bytes maximum residency (12 sample(s))</a>
<a class="sourceLine" id="cb2-7" data-line-number="7">      <span class="ex">61</span>,966,904 bytes maximum slop</a>
<a class="sourceLine" id="cb2-8" data-line-number="8">             <span class="ex">601</span> MB total memory in use (0 MB lost due to fragmentation)</a>
<a class="sourceLine" id="cb2-9" data-line-number="9"></a>
<a class="sourceLine" id="cb2-10" data-line-number="10">                                     <span class="ex">Tot</span> time (elapsed)  <span class="ex">Avg</span> pause  Max pause</a>
<a class="sourceLine" id="cb2-11" data-line-number="11">  <span class="ex">Gen</span>  0      3150 colls,     0 par    0.255s   0.255s     0.0001s    0.0222s</a>
<a class="sourceLine" id="cb2-12" data-line-number="12">  <span class="ex">Gen</span>  1        12 colls,     0 par    0.001s   0.001s     0.0001s    0.0001s</a>
<a class="sourceLine" id="cb2-13" data-line-number="13"></a>
<a class="sourceLine" id="cb2-14" data-line-number="14">  <span class="ex">INIT</span>    time    0.000s  (  0.000s elapsed)</a>
<a class="sourceLine" id="cb2-15" data-line-number="15">  <span class="ex">MUT</span>     time    0.461s  (  0.461s elapsed)</a>
<a class="sourceLine" id="cb2-16" data-line-number="16">  <span class="ex">GC</span>      time    0.256s  (  0.256s elapsed)</a>
<a class="sourceLine" id="cb2-17" data-line-number="17">  <span class="ex">EXIT</span>    time    0.017s  (  0.017s elapsed)</a>
<a class="sourceLine" id="cb2-18" data-line-number="18">  <span class="ex">Total</span>   time    0.734s  (  0.734s elapsed)</a>
<a class="sourceLine" id="cb2-19" data-line-number="19"></a>
<a class="sourceLine" id="cb2-20" data-line-number="20">  <span class="ex">%GC</span>     time      34.9%  (34.9% elapsed)</a>
<a class="sourceLine" id="cb2-21" data-line-number="21"></a>
<a class="sourceLine" id="cb2-22" data-line-number="22">  <span class="ex">Alloc</span> rate    6,496,221,499 bytes per MUT second</a>
<a class="sourceLine" id="cb2-23" data-line-number="23"></a>
<a class="sourceLine" id="cb2-24" data-line-number="24">  <span class="ex">Productivity</span>  65.1% of total user, 65.1% of total elapsed</a></code></pre></div>
<p>Well, these aren’t quite the same. I’m using GHC 8.2.2 while the author used 7.10.2. I also guess that my machine might be faster. That’s okay, I will just increase the maximum map size to 500000 elements and double the number of messages.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode diff"><code class="sourceCode diff"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="kw">diff --git a/tmp/Main_orig b/tmp/Main.hs</span></a>
<a class="sourceLine" id="cb3-2" data-line-number="2">index 4ffce03..e507d9f 100644</a>
<a class="sourceLine" id="cb3-3" data-line-number="3"><span class="dt">--- a/tmp/Main_orig</span></a>
<a class="sourceLine" id="cb3-4" data-line-number="4">+++ b/tmp/Main.hs</a>
<a class="sourceLine" id="cb3-5" data-line-number="5">@@ -18,9 +18,9 @@ pushMsg chan (Msg msgId msgContent) =</a>
<a class="sourceLine" id="cb3-6" data-line-number="6">     let</a>
<a class="sourceLine" id="cb3-7" data-line-number="7">       inserted = Map.insert msgId msgContent chan</a>
<a class="sourceLine" id="cb3-8" data-line-number="8">     in</a>
<a class="sourceLine" id="cb3-9" data-line-number="9">-      if 200000 &lt; Map.size inserted</a>
<a class="sourceLine" id="cb3-10" data-line-number="10">+      if 500000 &lt; Map.size inserted</a>
<a class="sourceLine" id="cb3-11" data-line-number="11">       then Map.deleteMin inserted</a>
<a class="sourceLine" id="cb3-12" data-line-number="12">       else inserted</a>
<a class="sourceLine" id="cb3-13" data-line-number="13"></a>
<a class="sourceLine" id="cb3-14" data-line-number="14"> main :: IO ()</a>
<a class="sourceLine" id="cb3-15" data-line-number="15">-main = Monad.foldM_ pushMsg Map.empty (map message [1..1000000])</a>
<a class="sourceLine" id="cb3-16" data-line-number="16">+main = Monad.foldM_ pushMsg Map.empty (map message [1..2000000])</a></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb4-1" data-line-number="1">[<span class="ex">nix-shell</span>:/tmp]$ ghc -O2 -optc-O3 -fforce-recomp Main.hs <span class="kw">&amp;&amp;</span> <span class="ex">./Main</span> +RTS -s</a>
<a class="sourceLine" id="cb4-2" data-line-number="2">[<span class="ex">1</span> of 1] Compiling Main             ( Main.hs, Main.o )</a>
<a class="sourceLine" id="cb4-3" data-line-number="3"><span class="ex">Linking</span> Main ...</a>
<a class="sourceLine" id="cb4-4" data-line-number="4">   <span class="ex">6</span>,186,436,048 bytes allocated in the heap</a>
<a class="sourceLine" id="cb4-5" data-line-number="5">     <span class="ex">773</span>,945,776 bytes copied during GC</a>
<a class="sourceLine" id="cb4-6" data-line-number="6">     <span class="ex">588</span>,034,760 bytes maximum residency (13 sample(s))</a>
<a class="sourceLine" id="cb4-7" data-line-number="7">     <span class="ex">154</span>,896,792 bytes maximum slop</a>
<a class="sourceLine" id="cb4-8" data-line-number="8">            <span class="ex">1499</span> MB total memory in use (0 MB lost due to fragmentation)</a>
<a class="sourceLine" id="cb4-9" data-line-number="9"></a>
<a class="sourceLine" id="cb4-10" data-line-number="10">                                     <span class="ex">Tot</span> time (elapsed)  <span class="ex">Avg</span> pause  Max pause</a>
<a class="sourceLine" id="cb4-11" data-line-number="11">  <span class="ex">Gen</span>  0      6499 colls,     0 par    0.567s   0.567s     0.0001s    0.0573s</a>
<a class="sourceLine" id="cb4-12" data-line-number="12">  <span class="ex">Gen</span>  1        13 colls,     0 par    0.001s   0.001s     0.0001s    0.0001s</a>
<a class="sourceLine" id="cb4-13" data-line-number="13"></a>
<a class="sourceLine" id="cb4-14" data-line-number="14">  <span class="ex">INIT</span>    time    0.000s  (  0.000s elapsed)</a>
<a class="sourceLine" id="cb4-15" data-line-number="15">  <span class="ex">MUT</span>     time    0.990s  (  0.990s elapsed)</a>
<a class="sourceLine" id="cb4-16" data-line-number="16">  <span class="ex">GC</span>      time    0.568s  (  0.568s elapsed)</a>
<a class="sourceLine" id="cb4-17" data-line-number="17">  <span class="ex">EXIT</span>    time    0.038s  (  0.038s elapsed)</a>
<a class="sourceLine" id="cb4-18" data-line-number="18">  <span class="ex">Total</span>   time    1.596s  (  1.596s elapsed)</a>
<a class="sourceLine" id="cb4-19" data-line-number="19"></a>
<a class="sourceLine" id="cb4-20" data-line-number="20">  <span class="ex">%GC</span>     time      35.6%  (35.6% elapsed)</a>
<a class="sourceLine" id="cb4-21" data-line-number="21"></a>
<a class="sourceLine" id="cb4-22" data-line-number="22">  <span class="ex">Alloc</span> rate    6,250,218,761 bytes per MUT second</a>
<a class="sourceLine" id="cb4-23" data-line-number="23"></a>
<a class="sourceLine" id="cb4-24" data-line-number="24">  <span class="ex">Productivity</span>  64.4% of total user, 64.4% of total elapsed</a></code></pre></div>
<p>Okay, I get a lot more total memory used but the pause is now very similar to original problem. Let’s work with this.</p>
<p>One important thing I want to mention is that the above code is obviously somewhat contrived and not optimal. Better (faster, less latency) answers were given on the SO answer but it’s not the point of this exercise.</p>
<h2 id="first-attempt-at-compacting-data">First attempt at compacting data</h2>
<p>Let’s use the <a href="https://hackage.haskell.org/package/compact">compact</a> package to put the working set (message map) in a compact region and see what happens. On first attempt we get an error:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="dt">Main</span><span class="fu">:</span> compaction failed<span class="fu">:</span> cannot compact pinned objects</a></code></pre></div>
<p>Well, that’s a problem. Haddock helpfully informs us why</p>
<pre><code>Pinned ByteArray# objects cannot be compacted. This is for a good reason: the
memory is pinned so that it can be referenced by address (the address
might be stored in a C data structure, for example), so we can&#39;t make
a copy of it to store in the Compact.</code></pre>
<p>Okay, let’s use ShortByteString instead which doesn’t use pinned memory.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="kw">module</span> <span class="dt">Main</span> (main) <span class="kw">where</span></a>
<a class="sourceLine" id="cb7-2" data-line-number="2"></a>
<a class="sourceLine" id="cb7-3" data-line-number="3"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Exception</span> <span class="kw">as</span> <span class="dt">Exception</span></a>
<a class="sourceLine" id="cb7-4" data-line-number="4"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Monad</span> <span class="kw">as</span> <span class="dt">Monad</span></a>
<a class="sourceLine" id="cb7-5" data-line-number="5"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">ByteString</span></a>
<a class="sourceLine" id="cb7-6" data-line-number="6"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString.Short</span> <span class="kw">as</span> <span class="dt">ByteString</span></a>
<a class="sourceLine" id="cb7-7" data-line-number="7"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map.Strict</span> <span class="kw">as</span> <span class="dt">Map</span></a>
<a class="sourceLine" id="cb7-8" data-line-number="8"></a>
<a class="sourceLine" id="cb7-9" data-line-number="9"><span class="kw">data</span> <span class="dt">Msg</span> <span class="fu">=</span> <span class="dt">Msg</span> <span class="fu">!</span><span class="dt">Int</span> <span class="fu">!</span><span class="dt">ByteString</span><span class="fu">.</span><span class="dt">ShortByteString</span></a>
<a class="sourceLine" id="cb7-10" data-line-number="10"></a>
<a class="sourceLine" id="cb7-11" data-line-number="11"><span class="kw">type</span> <span class="dt">Chan</span> <span class="fu">=</span> <span class="dt">Map.Map</span> <span class="dt">Int</span> <span class="dt">ByteString</span><span class="fu">.</span><span class="dt">ShortByteString</span></a>
<a class="sourceLine" id="cb7-12" data-line-number="12"></a>
<a class="sourceLine" id="cb7-13" data-line-number="13"><span class="ot">message ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Msg</span></a>
<a class="sourceLine" id="cb7-14" data-line-number="14">message n <span class="fu">=</span> <span class="dt">Msg</span> n (<span class="dt">ByteString</span><span class="fu">.</span>toShort <span class="fu">$</span> <span class="dt">ByteString</span><span class="fu">.</span>replicate <span class="dv">1024</span> (fromIntegral n))</a>
<a class="sourceLine" id="cb7-15" data-line-number="15"></a>
<a class="sourceLine" id="cb7-16" data-line-number="16"><span class="ot">pushMsg ::</span> <span class="dt">Chan</span> <span class="ot">-&gt;</span> <span class="dt">Msg</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">Chan</span></a>
<a class="sourceLine" id="cb7-17" data-line-number="17">pushMsg chan (<span class="dt">Msg</span> msgId msgContent) <span class="fu">=</span></a>
<a class="sourceLine" id="cb7-18" data-line-number="18">  Exception.evaluate <span class="fu">$</span></a>
<a class="sourceLine" id="cb7-19" data-line-number="19">    <span class="kw">let</span></a>
<a class="sourceLine" id="cb7-20" data-line-number="20">      inserted <span class="fu">=</span> Map.insert msgId msgContent chan</a>
<a class="sourceLine" id="cb7-21" data-line-number="21">    <span class="kw">in</span></a>
<a class="sourceLine" id="cb7-22" data-line-number="22">      <span class="kw">if</span> <span class="dv">500000</span> <span class="fu">&lt;</span> Map.size inserted</a>
<a class="sourceLine" id="cb7-23" data-line-number="23">      <span class="kw">then</span> Map.deleteMin inserted</a>
<a class="sourceLine" id="cb7-24" data-line-number="24">      <span class="kw">else</span> inserted</a>
<a class="sourceLine" id="cb7-25" data-line-number="25"></a>
<a class="sourceLine" id="cb7-26" data-line-number="26"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb7-27" data-line-number="27">main <span class="fu">=</span> <span class="dt">Monad</span><span class="fu">.</span>foldM_ pushMsg Map.empty (map message [<span class="dv">1</span><span class="fu">..</span><span class="dv">2000000</span>])</a></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="ex">Linking</span> Main_short ...</a>
<a class="sourceLine" id="cb8-2" data-line-number="2">   <span class="ex">8</span>,298,436,048 bytes allocated in the heap</a>
<a class="sourceLine" id="cb8-3" data-line-number="3">   <span class="ex">8</span>,157,334,544 bytes copied during GC</a>
<a class="sourceLine" id="cb8-4" data-line-number="4">     <span class="ex">560</span>,033,704 bytes maximum residency (18 sample(s))</a>
<a class="sourceLine" id="cb8-5" data-line-number="5">     <span class="ex">122</span>,683,480 bytes maximum slop</a>
<a class="sourceLine" id="cb8-6" data-line-number="6">            <span class="ex">1748</span> MB total memory in use (0 MB lost due to fragmentation)</a>
<a class="sourceLine" id="cb8-7" data-line-number="7"></a>
<a class="sourceLine" id="cb8-8" data-line-number="8">                                     <span class="ex">Tot</span> time (elapsed)  <span class="ex">Avg</span> pause  Max pause</a>
<a class="sourceLine" id="cb8-9" data-line-number="9">  <span class="ex">Gen</span>  0      9156 colls,     0 par    1.511s   1.511s     0.0002s    0.1852s</a>
<a class="sourceLine" id="cb8-10" data-line-number="10">  <span class="ex">Gen</span>  1        18 colls,     0 par    0.002s   0.002s     0.0001s    0.0002s</a>
<a class="sourceLine" id="cb8-11" data-line-number="11"></a>
<a class="sourceLine" id="cb8-12" data-line-number="12">  <span class="ex">INIT</span>    time    0.000s  (  0.000s elapsed)</a>
<a class="sourceLine" id="cb8-13" data-line-number="13">  <span class="ex">MUT</span>     time    0.872s  (  0.872s elapsed)</a>
<a class="sourceLine" id="cb8-14" data-line-number="14">  <span class="ex">GC</span>      time    1.512s  (  1.513s elapsed)</a>
<a class="sourceLine" id="cb8-15" data-line-number="15">  <span class="ex">EXIT</span>    time    0.037s  (  0.037s elapsed)</a>
<a class="sourceLine" id="cb8-16" data-line-number="16">  <span class="ex">Total</span>   time    2.422s  (  2.422s elapsed)</a>
<a class="sourceLine" id="cb8-17" data-line-number="17"></a>
<a class="sourceLine" id="cb8-18" data-line-number="18">  <span class="ex">%GC</span>     time      62.4%  (62.4% elapsed)</a>
<a class="sourceLine" id="cb8-19" data-line-number="19"></a>
<a class="sourceLine" id="cb8-20" data-line-number="20">  <span class="ex">Alloc</span> rate    9,512,524,179 bytes per MUT second</a>
<a class="sourceLine" id="cb8-21" data-line-number="21"></a>
<a class="sourceLine" id="cb8-22" data-line-number="22">  <span class="ex">Productivity</span>  37.6% of total user, 37.6% of total elapsed</a></code></pre></div>
<p>Due to the additional overheads our pauses are through the roof. Let’s go back to original numbers of 200k and million messages:</p>
<pre><code>Linking Main_short ...
   4,052,460,128 bytes allocated in the heap
   4,110,484,224 bytes copied during GC
     224,033,704 bytes maximum residency (18 sample(s))
      49,079,384 bytes maximum slop
             700 MB total memory in use (0 MB lost due to fragmentation)

                                     Tot time (elapsed)  Avg pause  Max pause
  Gen  0      4477 colls,     0 par    0.734s   0.735s     0.0002s    0.0717s
  Gen  1        18 colls,     0 par    0.002s   0.002s     0.0001s    0.0002s

  INIT    time    0.000s  (  0.000s elapsed)
  MUT     time    0.416s  (  0.416s elapsed)
  GC      time    0.736s  (  0.736s elapsed)
  EXIT    time    0.014s  (  0.014s elapsed)
  Total   time    1.166s  (  1.166s elapsed)

  %GC     time      63.1%  (63.1% elapsed)

  Alloc rate    9,746,445,658 bytes per MUT second

  Productivity  36.9% of total user, 36.9% of total elapsed</code></pre>
<p>OK, let’s work with this.</p>
<h2 id="second-attempt-at-compacting-data">Second attempt at compacting data</h2>
<p>Now that we’re back to original figures (ish) we can actually compact data. Let’s try a naive approach: stick the whole map into a compact region:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb10-1" data-line-number="1"><span class="kw">module</span> <span class="dt">Main</span> (main) <span class="kw">where</span></a>
<a class="sourceLine" id="cb10-2" data-line-number="2"></a>
<a class="sourceLine" id="cb10-3" data-line-number="3"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Exception</span> <span class="kw">as</span> <span class="dt">Exception</span></a>
<a class="sourceLine" id="cb10-4" data-line-number="4"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Control.Monad</span> <span class="kw">as</span> <span class="dt">Monad</span></a>
<a class="sourceLine" id="cb10-5" data-line-number="5"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">ByteString</span></a>
<a class="sourceLine" id="cb10-6" data-line-number="6"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString.Short</span> <span class="kw">as</span> <span class="dt">ByteString</span></a>
<a class="sourceLine" id="cb10-7" data-line-number="7"><span class="kw">import</span>           <span class="dt">Data.Compact</span> (<span class="dt">Compact</span>)</a>
<a class="sourceLine" id="cb10-8" data-line-number="8"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Compact</span> <span class="kw">as</span> <span class="dt">Compact</span></a>
<a class="sourceLine" id="cb10-9" data-line-number="9"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Map.Strict</span> <span class="kw">as</span> <span class="dt">Map</span></a>
<a class="sourceLine" id="cb10-10" data-line-number="10"></a>
<a class="sourceLine" id="cb10-11" data-line-number="11"><span class="kw">data</span> <span class="dt">Msg</span> <span class="fu">=</span> <span class="dt">Msg</span> <span class="fu">!</span><span class="dt">Int</span> <span class="fu">!</span><span class="dt">ByteString</span><span class="fu">.</span><span class="dt">ShortByteString</span></a>
<a class="sourceLine" id="cb10-12" data-line-number="12"></a>
<a class="sourceLine" id="cb10-13" data-line-number="13"><span class="kw">type</span> <span class="dt">Chan</span> <span class="fu">=</span> <span class="dt">Map.Map</span> <span class="dt">Int</span> <span class="dt">ByteString</span><span class="fu">.</span><span class="dt">ShortByteString</span></a>
<a class="sourceLine" id="cb10-14" data-line-number="14"></a>
<a class="sourceLine" id="cb10-15" data-line-number="15"><span class="ot">message ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Msg</span></a>
<a class="sourceLine" id="cb10-16" data-line-number="16">message n <span class="fu">=</span> <span class="dt">Msg</span> n (<span class="dt">ByteString</span><span class="fu">.</span>toShort <span class="fu">$</span> <span class="dt">ByteString</span><span class="fu">.</span>replicate <span class="dv">1024</span> (fromIntegral n))</a>
<a class="sourceLine" id="cb10-17" data-line-number="17"></a>
<a class="sourceLine" id="cb10-18" data-line-number="18"><span class="ot">pushMsg ::</span> <span class="dt">Compact</span> <span class="dt">Chan</span> <span class="ot">-&gt;</span> <span class="dt">Msg</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Compact</span> <span class="dt">Chan</span>)</a>
<a class="sourceLine" id="cb10-19" data-line-number="19">pushMsg chan (<span class="dt">Msg</span> msgId msgContent) <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb10-20" data-line-number="20">  <span class="kw">let</span> inserted <span class="fu">=</span> Map.insert msgId msgContent (Compact.getCompact chan)</a>
<a class="sourceLine" id="cb10-21" data-line-number="21">  Compact.compactAdd chan <span class="fu">$</span></a>
<a class="sourceLine" id="cb10-22" data-line-number="22">    <span class="kw">if</span> <span class="dv">200000</span> <span class="fu">&lt;</span> Map.size inserted</a>
<a class="sourceLine" id="cb10-23" data-line-number="23">      <span class="kw">then</span> Map.deleteMin inserted</a>
<a class="sourceLine" id="cb10-24" data-line-number="24">      <span class="kw">else</span> inserted</a>
<a class="sourceLine" id="cb10-25" data-line-number="25"></a>
<a class="sourceLine" id="cb10-26" data-line-number="26"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb10-27" data-line-number="27">main <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb10-28" data-line-number="28">  startMap <span class="ot">&lt;-</span> Compact.compact Map.empty</a>
<a class="sourceLine" id="cb10-29" data-line-number="29">  <span class="dt">Monad</span><span class="fu">.</span>foldM_ pushMsg startMap (map message [<span class="dv">1</span><span class="fu">..</span><span class="dv">1000000</span>])</a></code></pre></div>
<p>Let’s run:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="ex">Linking</span> Main_short ...</a>
<a class="sourceLine" id="cb11-2" data-line-number="2">   <span class="ex">7</span>,006,681,216 bytes allocated in the heap</a>
<a class="sourceLine" id="cb11-3" data-line-number="3">       <span class="ex">7</span>,154,440 bytes copied during GC</a>
<a class="sourceLine" id="cb11-4" data-line-number="4">   <span class="ex">1</span>,869,743,096 bytes maximum residency (12 sample(s))</a>
<a class="sourceLine" id="cb11-5" data-line-number="5">          <span class="ex">29</span>,352 bytes maximum slop</a>
<a class="sourceLine" id="cb11-6" data-line-number="6">            <span class="ex">2759</span> MB total memory in use (42 MB lost due to fragmentation)</a>
<a class="sourceLine" id="cb11-7" data-line-number="7"></a>
<a class="sourceLine" id="cb11-8" data-line-number="8">                                     <span class="ex">Tot</span> time (elapsed)  <span class="ex">Avg</span> pause  Max pause</a>
<a class="sourceLine" id="cb11-9" data-line-number="9">  <span class="ex">Gen</span>  0      4627 colls,     0 par    0.026s   0.026s     0.0000s    0.0000s</a>
<a class="sourceLine" id="cb11-10" data-line-number="10">  <span class="ex">Gen</span>  1        12 colls,     0 par    0.000s   0.000s     0.0000s    0.0000s</a>
<a class="sourceLine" id="cb11-11" data-line-number="11"></a>
<a class="sourceLine" id="cb11-12" data-line-number="12">  <span class="ex">INIT</span>    time    0.000s  (  0.000s elapsed)</a>
<a class="sourceLine" id="cb11-13" data-line-number="13">  <span class="ex">MUT</span>     time    2.263s  (  2.264s elapsed)</a>
<a class="sourceLine" id="cb11-14" data-line-number="14">  <span class="ex">GC</span>      time    0.026s  (  0.026s elapsed)</a>
<a class="sourceLine" id="cb11-15" data-line-number="15">  <span class="ex">EXIT</span>    time    0.056s  (  0.056s elapsed)</a>
<a class="sourceLine" id="cb11-16" data-line-number="16">  <span class="ex">Total</span>   time    2.345s  (  2.345s elapsed)</a>
<a class="sourceLine" id="cb11-17" data-line-number="17"></a>
<a class="sourceLine" id="cb11-18" data-line-number="18">  <span class="ex">%GC</span>     time       1.1%  (1.1% elapsed)</a>
<a class="sourceLine" id="cb11-19" data-line-number="19"></a>
<a class="sourceLine" id="cb11-20" data-line-number="20">  <span class="ex">Alloc</span> rate    3,095,601,467 bytes per MUT second</a>
<a class="sourceLine" id="cb11-21" data-line-number="21"></a>
<a class="sourceLine" id="cb11-22" data-line-number="22">  <span class="ex">Productivity</span>  98.9% of total user, 98.9% of total elapsed</a></code></pre></div>
<p>We completely eliminated the latency due to GC! We don’t really hold to any real data anymore so all the collections are extremely quick. What’s the catch?</p>
<p>Well, few things.</p>
<ol type="1">
<li>Our program is twice as slow. We sacrificed throughput for latency. This was OK for Pusher guys but 2x is quite poor. If we could go faster that would be nice.</li>
<li>Our total memory used is through the roof: 4x increase with 10x increase in resident memory. We’re only ever appending data to the region, never getting rid of data within it. This means our region is holding onto all 1000000 messages.</li>
</ol>
<p>Can we try to do something more reasonable? What if we didn’t have a million messages but unbounded amount?</p>
<h3 id="memory-usage">Memory usage</h3>
<p>How do we lower the memory usage? We know where it’s coming from: the data in the region is never traced, never copied and therefore nothing is ever freed. The GC does not look in the region at all. To free the data in a region, we have to copy the live data we’re interested it out to a different region and free the region itself. This is pretty much exactly what GHC’s GC does so it’s like invoking the garbage collector manually for a region.</p>
<p>In order to copy out data to a new region, we simple use <code>compact</code> on the value and return the new region, letting the old region be freed. However we can’t (or rather, shouldn’t) do this on every new message: that’s like running garbage collection on every message that comes in. Notably, this is bad and I’m not even patient enough to wait for it to terminate:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb12-1" data-line-number="1">pushMsg chan (<span class="dt">Msg</span> msgId msgContent) <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb12-2" data-line-number="2">  <span class="kw">let</span> inserted <span class="fu">=</span> Map.insert msgId msgContent (Compact.getCompact chan)</a>
<a class="sourceLine" id="cb12-3" data-line-number="3">      newInserted <span class="fu">=</span> <span class="kw">if</span> <span class="dv">200000</span> <span class="fu">&lt;</span> Map.size inserted</a>
<a class="sourceLine" id="cb12-4" data-line-number="4">        <span class="kw">then</span> Map.deleteMin inserted</a>
<a class="sourceLine" id="cb12-5" data-line-number="5">        <span class="kw">else</span> inserted</a>
<a class="sourceLine" id="cb12-6" data-line-number="6">  Compact.compact newInserted</a></code></pre></div>
<p>You may think we can improve this: we only need to collect when we throw away old data, right?</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb13-1" data-line-number="1">pushMsg chan (<span class="dt">Msg</span> msgId msgContent) <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb13-2" data-line-number="2">  <span class="kw">let</span> inserted <span class="fu">=</span> Map.insert msgId msgContent (Compact.getCompact chan)</a>
<a class="sourceLine" id="cb13-3" data-line-number="3">  <span class="kw">if</span> <span class="dv">200000</span> <span class="fu">&lt;</span> Map.size inserted</a>
<a class="sourceLine" id="cb13-4" data-line-number="4">    <span class="kw">then</span> Compact.compact (Map.deleteMin inserted)</a>
<a class="sourceLine" id="cb13-5" data-line-number="5">    <span class="kw">else</span> Compact.compactAdd chan inserted</a></code></pre></div>
<p>Well, this is slightly better but only by some constant factor: after the buffer fills, we’re back to copying all the time.</p>
<p>What about a slightly more clever solution? We can specify how much memory we want to use and when we want to copy the data into a new region. That is, simply copy every <code>n</code> number of messages. In the worst case, we have 200k messages in buffer + <code>n</code> removed messages. This gives us more fine grained control lover exactly how much space we’re willing to allocate (at most) and how often copying happens. Most importantly, it allows us to <em>reliably</em> copy a known amount of data (up to a bound) which we can directly correlate to GC pause times! I’m going to use the fact that message IDs are sequential but you could trivially maintain own counter instead. Let’s make the code copy to a new region every <code>n</code> messages with <code>n</code> being configurable at command line.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb14-1" data-line-number="1"><span class="ot">pushMsg ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Compact</span> <span class="dt">Chan</span> <span class="ot">-&gt;</span> <span class="dt">Msg</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Compact</span> <span class="dt">Chan</span>)</a>
<a class="sourceLine" id="cb14-2" data-line-number="2">pushMsg collectEvery chan (<span class="dt">Msg</span> msgId msgContent) <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb14-3" data-line-number="3">  <span class="kw">let</span> inserted <span class="fu">=</span> Map.insert msgId msgContent (Compact.getCompact chan)</a>
<a class="sourceLine" id="cb14-4" data-line-number="4">      newInserted <span class="fu">=</span> <span class="kw">if</span> <span class="dv">200000</span> <span class="fu">&lt;</span> Map.size inserted</a>
<a class="sourceLine" id="cb14-5" data-line-number="5">        <span class="kw">then</span> Map.deleteMin inserted</a>
<a class="sourceLine" id="cb14-6" data-line-number="6">        <span class="kw">else</span> inserted</a>
<a class="sourceLine" id="cb14-7" data-line-number="7">  <span class="kw">if</span> msgId <span class="ot">`mod`</span> collectEvery <span class="fu">==</span> <span class="dv">0</span></a>
<a class="sourceLine" id="cb14-8" data-line-number="8">    <span class="kw">then</span> Compact.compact newInserted</a>
<a class="sourceLine" id="cb14-9" data-line-number="9">    <span class="kw">else</span> Compact.compactAdd chan newInserted</a>
<a class="sourceLine" id="cb14-10" data-line-number="10"></a>
<a class="sourceLine" id="cb14-11" data-line-number="11"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb14-12" data-line-number="12">main <span class="fu">=</span> getArgs <span class="fu">&gt;&gt;=</span> \<span class="kw">case</span></a>
<a class="sourceLine" id="cb14-13" data-line-number="13">  [ce] <span class="ot">-&gt;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb14-14" data-line-number="14">    startMap <span class="ot">&lt;-</span> Compact.compact Map.empty</a>
<a class="sourceLine" id="cb14-15" data-line-number="15">    <span class="dt">Monad</span><span class="fu">.</span>foldM_ (pushMsg <span class="fu">$!</span> read ce) startMap (map message [<span class="dv">1</span><span class="fu">..</span><span class="dv">1000000</span>])</a>
<a class="sourceLine" id="cb14-16" data-line-number="16">  _ <span class="ot">-&gt;</span> error <span class="st">&quot;usage: progname collectevery&quot;</span></a></code></pre></div>
<p>This means that for any <code>n</code> we give the program, it’s going to copy the data out into a new region. Let’s run it for every <code>n</code> from 5000 until 1005000: I’m not running it for less than 5000 because I don’t want to wait through all the copying and I’m running it over 1000000 to show a case where no copy happens.</p>
<figure>
<img src="images/compact_large_x.png" alt="varyingNlargerange" /><figcaption>varyingNlargerange</figcaption>
</figure>
<p>Here is a second run for smaller range of values to cut off the extremes (100k - 700k):</p>
<figure>
<img src="images/compact_small_x.png" alt="varyingNsmallrange" /><figcaption>varyingNsmallrange</figcaption>
</figure>
<p>Here is a third run between 1k and 100k as this seems to be quite an interesting region, intervals of 1000:</p>
<figure>
<img src="images/compact_tiny_x.png" alt="varyingNtinyrange" /><figcaption>varyingNtinyrange</figcaption>
</figure>
<p>And finally a smallest run between 40k and 80k as this seems to be somewhat of an optimal range for our example.</p>
<figure>
<img src="images/compact_smallest_x.png" alt="varyingNsmallestrange" /><figcaption>varyingNsmallestrange</figcaption>
</figure>
<h2 id="conclusion">Conclusion</h2>
<p>From the charts, we see that there are areas for this particular use-case where we can keep GC pauses very low. The original requirement was 10ms. Original SO question demonstrated 50ms GC pauses. In the charts we can see many areas below 5ms and ranges where it’s 1-2ms while maintaining relatively low residency and about the same factor of slowdown as when we never collected. On the extreme side where we stored all messages in the region, our pauses go to ~0: we don’t have any real data to traverse so GC doesn’t pause for long.</p>
<p>The throughput is poor. 2x-3x times slower. Part of the slowdown is artificial: I had to make things work with ShortByteStrings, I’m creating those from ByteString &amp;c.</p>
<p>The main issue with this case study is that the buffer of messages changes and we have to manage it, balancing memory vs latency vs throughput. Compact regions really shine when you have a chunk of long-lived data that you want to access throughout your program. I would say that using it with data that’s changing frequently is a poor use. Even then, I’m actually pleasantly surprised: if you can take the 2-3x throughput hit but really care about latency, there is now a light in the tunnel for you. There is also additional memory cost but in a lot of cases if you’re willing to trade throughput, you probably can afford additional residency too.</p>
<p>Of course the very first thing to do would be to try to make-do without this: compact regions are not magic and they have costs and restrictions. They seem to be very good at what they do (based on numbers from the paper) but they are not the silver bullet. If you can exercise some smarter programming to get by, you should do that first.</p>
<p>Lastly, my benchmarks are very poor, I sample each N just once. Some of them were done multiple times as the charts generated were from separate runs. I would not use anything you see here as scientific fact nor a template for how to use compact regions. This was merely me checking out the feature and trying to apply it to an example I knew. I think if I were to re-do this post, I would take the time to set up much more comprehensive benchmarking with multiple versions of code side-by-side, pretty metrics &amp;c.</p>
<p>In the future if I have an application with long-lived mostly-static data, I will certainly keep compact regions in mind.</p>
<h2 id="appendix">Appendix</h2>
<p>I used the following code to generate the chart seen earlier. This is just throw-away code so it’s just here for completion.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb15-1" data-line-number="1"><span class="kw">module</span> <span class="dt">Main</span> (main) <span class="kw">where</span></a>
<a class="sourceLine" id="cb15-2" data-line-number="2"></a>
<a class="sourceLine" id="cb15-3" data-line-number="3"><span class="kw">import</span> <span class="dt">Control.Monad</span></a>
<a class="sourceLine" id="cb15-4" data-line-number="4"><span class="kw">import</span> <span class="dt">Graphics.Rendering.Chart</span></a>
<a class="sourceLine" id="cb15-5" data-line-number="5"><span class="kw">import</span> <span class="dt">Graphics.Rendering.Chart.Backend.Cairo</span> (renderableToFile)</a>
<a class="sourceLine" id="cb15-6" data-line-number="6"><span class="kw">import</span> <span class="dt">Graphics.Rendering.Chart.Easy</span></a>
<a class="sourceLine" id="cb15-7" data-line-number="7"><span class="kw">import</span> <span class="dt">Graphics.Rendering.Chart.Grid</span></a>
<a class="sourceLine" id="cb15-8" data-line-number="8"><span class="kw">import</span> <span class="dt">System.Process</span></a>
<a class="sourceLine" id="cb15-9" data-line-number="9"></a>
<a class="sourceLine" id="cb15-10" data-line-number="10"><span class="kw">data</span> <span class="dt">Stats</span> <span class="fu">=</span> <span class="dt">Stats</span></a>
<a class="sourceLine" id="cb15-11" data-line-number="11">  {<span class="ot"> nVal ::</span> <span class="fu">!</span><span class="dt">Int</span></a>
<a class="sourceLine" id="cb15-12" data-line-number="12">    <span class="co">-- | MBs</span></a>
<a class="sourceLine" id="cb15-13" data-line-number="13">  ,<span class="ot"> residency ::</span> <span class="fu">!</span><span class="dt">Double</span></a>
<a class="sourceLine" id="cb15-14" data-line-number="14">  ,<span class="ot"> maxPause ::</span> <span class="fu">!</span><span class="dt">Double</span></a>
<a class="sourceLine" id="cb15-15" data-line-number="15">  ,<span class="ot"> totalTime ::</span> <span class="fu">!</span><span class="dt">Double</span></a>
<a class="sourceLine" id="cb15-16" data-line-number="16">  } <span class="kw">deriving</span> <span class="dt">Show</span></a>
<a class="sourceLine" id="cb15-17" data-line-number="17"></a>
<a class="sourceLine" id="cb15-18" data-line-number="18"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb15-19" data-line-number="19">main <span class="fu">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb15-20" data-line-number="20">  <span class="co">-- GHC RTS options do not allow you to see max pause in a nice</span></a>
<a class="sourceLine" id="cb15-21" data-line-number="21">  <span class="co">-- format. GHC.Stats doesn&#39;t return it. It&#39;s not in -t</span></a>
<a class="sourceLine" id="cb15-22" data-line-number="22">  <span class="co">-- --machine-readable output either. Just &quot;parse&quot; -s output, this is</span></a>
<a class="sourceLine" id="cb15-23" data-line-number="23">  <span class="co">-- a throw-away program anyway.</span></a>
<a class="sourceLine" id="cb15-24" data-line-number="24">  times <span class="ot">&lt;-</span> forM [<span class="dv">5000</span>, <span class="dv">10000</span> <span class="fu">..</span> <span class="dv">1005000</span>] <span class="fu">$</span> \i <span class="ot">-&gt;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb15-25" data-line-number="25">    (_, _, out) <span class="ot">&lt;-</span> readProcessWithExitCode <span class="st">&quot;/tmp/Main_short&quot;</span> [show i, <span class="st">&quot;+RTS&quot;</span>, <span class="st">&quot;-s&quot;</span>] <span class="st">&quot;&quot;</span></a>
<a class="sourceLine" id="cb15-26" data-line-number="26">    <span class="kw">let</span> ls <span class="fu">=</span> lines out</a>
<a class="sourceLine" id="cb15-27" data-line-number="27">        res <span class="fu">=</span> read <span class="fu">.</span> filter (<span class="fu">/=</span> <span class="ch">&#39;,&#39;</span>) <span class="fu">.</span> head <span class="fu">.</span> words <span class="fu">$</span> ls <span class="fu">!!</span> <span class="dv">2</span></a>
<a class="sourceLine" id="cb15-28" data-line-number="28">        pause <span class="fu">=</span> read <span class="fu">.</span> filter (<span class="fu">/=</span> <span class="ch">&#39;s&#39;</span>) <span class="fu">.</span> last <span class="fu">.</span> words <span class="fu">$</span> ls <span class="fu">!!</span> <span class="dv">7</span></a>
<a class="sourceLine" id="cb15-29" data-line-number="29">        totTime <span class="fu">=</span> read <span class="fu">.</span> filter (<span class="fu">/=</span> <span class="ch">&#39;s&#39;</span>) <span class="fu">.</span> (<span class="fu">!!</span> <span class="dv">4</span>) <span class="fu">.</span> words <span class="fu">$</span> ls <span class="fu">!!</span> <span class="dv">14</span></a>
<a class="sourceLine" id="cb15-30" data-line-number="30">    print i</a>
<a class="sourceLine" id="cb15-31" data-line-number="31">    pure <span class="fu">$!</span> <span class="dt">Stats</span></a>
<a class="sourceLine" id="cb15-32" data-line-number="32">      { residency <span class="fu">=</span> fromIntegral (<span class="ot">res ::</span> <span class="dt">Int</span>) <span class="fu">/</span> <span class="dv">1024</span> <span class="fu">/</span> <span class="dv">1024</span></a>
<a class="sourceLine" id="cb15-33" data-line-number="33">      , maxPause <span class="fu">=</span> pause</a>
<a class="sourceLine" id="cb15-34" data-line-number="34">      , totalTime <span class="fu">=</span> totTime</a>
<a class="sourceLine" id="cb15-35" data-line-number="35">      , nVal <span class="fu">=</span> i</a>
<a class="sourceLine" id="cb15-36" data-line-number="36">      }</a>
<a class="sourceLine" id="cb15-37" data-line-number="37">  void <span class="fu">$</span> renderableToFile def <span class="st">&quot;/tmp/results.png&quot;</span> <span class="fu">$</span> fillBackground def <span class="fu">$</span> gridToRenderable <span class="fu">$</span></a>
<a class="sourceLine" id="cb15-38" data-line-number="38">    <span class="kw">let</span> title <span class="fu">=</span> setPickFn nullPickFn <span class="fu">$</span> label def <span class="dt">HTA_Centre</span> <span class="dt">VTA_Centre</span> <span class="st">&quot;Effect of copies for different N&quot;</span></a>
<a class="sourceLine" id="cb15-39" data-line-number="39">    <span class="kw">in</span> title <span class="ot">`wideAbove`</span> aboveN</a>
<a class="sourceLine" id="cb15-40" data-line-number="40">         [ aboveN</a>
<a class="sourceLine" id="cb15-41" data-line-number="41">           [ layoutToGrid <span class="fu">$</span> mkChart <span class="st">&quot;residency&quot;</span> <span class="st">&quot;MiB&quot;</span> red [ (nVal s, residency s) <span class="fu">|</span> s <span class="ot">&lt;-</span> times ]</a>
<a class="sourceLine" id="cb15-42" data-line-number="42">           , layoutToGrid <span class="fu">$</span> mkChart <span class="st">&quot;max pause&quot;</span> <span class="st">&quot;sec&quot;</span> green [ (nVal s, maxPause s) <span class="fu">|</span> s <span class="ot">&lt;-</span> times ]</a>
<a class="sourceLine" id="cb15-43" data-line-number="43">           , layoutToGrid <span class="fu">$</span> mkChart <span class="st">&quot;total time&quot;</span> <span class="st">&quot;sec&quot;</span> blue [ (nVal s, totalTime s) <span class="fu">|</span> s <span class="ot">&lt;-</span> times ]</a>
<a class="sourceLine" id="cb15-44" data-line-number="44">           ]</a>
<a class="sourceLine" id="cb15-45" data-line-number="45">         ]</a>
<a class="sourceLine" id="cb15-46" data-line-number="46"></a>
<a class="sourceLine" id="cb15-47" data-line-number="47">mkChart</a>
<a class="sourceLine" id="cb15-48" data-line-number="48"><span class="ot">  ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb15-49" data-line-number="49">  <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb15-50" data-line-number="50">  <span class="ot">-&gt;</span> <span class="dt">Colour</span> <span class="dt">Double</span></a>
<a class="sourceLine" id="cb15-51" data-line-number="51">  <span class="ot">-&gt;</span> [(<span class="dt">Int</span>, <span class="dt">Double</span>)]</a>
<a class="sourceLine" id="cb15-52" data-line-number="52">  <span class="ot">-&gt;</span> <span class="dt">Layout</span> <span class="dt">Int</span> <span class="dt">Double</span></a>
<a class="sourceLine" id="cb15-53" data-line-number="53">mkChart lbl units c vs <span class="fu">=</span> execEC <span class="fu">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb15-54" data-line-number="54">  layout_y_axis <span class="fu">.</span> laxis_title <span class="fu">.=</span> units</a>
<a class="sourceLine" id="cb15-55" data-line-number="55">  layout_x_axis <span class="fu">.</span> laxis_title <span class="fu">.=</span> <span class="st">&quot;Messages before compact copy.&quot;</span></a>
<a class="sourceLine" id="cb15-56" data-line-number="56">  layout_plots <span class="fu">.=</span></a>
<a class="sourceLine" id="cb15-57" data-line-number="57">    [ toPlot <span class="fu">$</span> plot_lines_title <span class="fu">.~</span> lbl</a>
<a class="sourceLine" id="cb15-58" data-line-number="58">             <span class="fu">$</span> plot_lines_values <span class="fu">.~</span> [vs]</a>
<a class="sourceLine" id="cb15-59" data-line-number="59">             <span class="fu">$</span> plot_lines_style <span class="fu">.</span> line_color <span class="fu">.~</span> opaque c</a>
<a class="sourceLine" id="cb15-60" data-line-number="60">             <span class="fu">$</span> def</a>
<a class="sourceLine" id="cb15-61" data-line-number="61">    ]</a></code></pre></div>
]]></summary>
</entry>
<entry>
    <title>A case for .Internal modules.</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2018-03-02-A-case-for-Internal-modules.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2018-03-02-A-case-for-Internal-modules.html</id>
    <published>2018-03-02T22:20:00Z</published>
    <updated>2018-03-02T22:20:00Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on March  2, 2018
    
        by Fūzetsu
    
</div>

<p>Many libraries expose <code>.Internal</code> modules: these are module that contain functions that are unsafe, unstable, with no guarantees and quite often, fast. This is great if you Know What You Are Doing™.</p>
<p>Sadly, not all package authors seem to do this. Part of the motivation is that in principle, it shouldn’t be needed. Indeed this is what I was told by a co-worker <a href="https://github.com/tweag/rules_haskell/issues/152#issuecomment-367712602">on this seemingly unrelated rules_haskell issue</a>. After a brief chat on Slack however, I was able to convince him otherwise. Below is a paraphrasing of my arguments and reason why I think <code>.Internal</code> modules are a good thing and you should be exposing them. Find below some ramblings on why you should expose internals of your libraries.</p>
<h2 id="expose-the-internals-please.">Expose the internals, please.</h2>
<ol type="1">
<li><p>I love your library but it can’t cover all my use-cases. It’s wrong for it to try. Please let me use the back doors.</p>
<p>This is extremely common. I’m using your library and it’s going great. I write my program and it runs fast. I look through <a href="http://www.brendangregg.com/perf.html">perf</a> report and GHC’s profiling output. It could be faster. I know how to make it faster. But I can’t make it faster because I’m relying on your library which insists on taking the slow route.</p>
<p>This is rarely the fault of the library. Libraries provide abstractions, data types, functions on those types and give us guarantees. To preserve the invariants, it needs to protect itself from the dumb users.</p>
<p>I will give the same example that I gave when I initially discussed this. I was writing a small program recently and using a min priority queue. I was also tracking the maximal element that was inserted: something the library could not offer me in constant time and nor should it. When I wanted to insert this maximal element into the queue however, I have a problem: the library will perform linear in the size of the queue number of comparisons; it has to know where to insert the element after all. So <a href="https://github.com/lspitzner/pqueue/issues/18">I created an issue in pqueue</a> library to let me do this. The easiest way is to expose the data type constructors in an <code>.Internal</code> module and let me do the traversal myself without doing the comparisons.</p>
<p>Notably I want to stress that this is of no fault of the library: inserting arbitrary element in arbitrary place breaks the queue. It is only with my external knowledge that I am able to insert it safely.</p>
<p>Could better library design have stopped this? I want to argue that no if we only have finite amount of time to spend. If we were using something like Agda or even just more esoteric parts of Haskell, we could actually improve the library to expose such a function. We could have <code>insertMaximal</code> that requires proof that the element is maximal. I could produce it. The library is not about providing this, would likely make the common case API more awkward and is generally probably not the best use of the author’s time. Just give me the constructors, please.</p></li>
<li><p>I love your library and you have a function that does the exact thing I need already but… it’s not exported.</p>
<p>Very frequently library authors will implement certain things for their own convenience and only export a nice API to the user. This is OK if the API works for you but if something is missing, it’s incredibly frustrating to find that the exact code you need already exists. Frequently it’s not even unsafe code. I could give another <code>pqueue</code> example but let’s look at a different one for variety.</p>
<p><a href="https://hackage.haskell.org/package/text-show">text-show</a> is a package that provides a <code>Show</code>-like type class that instead of going to <code>String</code> or <code>String</code> builder (<code>String -&gt; String</code>), uses <code>Text</code> instead. This is great because <code>String</code> is the devil and you shouldn’t be using it. Recently I found myself wanting to save some memory so I reached for <a href="https://hackage.haskell.org/package/bytestring-0.10.8.2/docs/Data-ByteString-Short.html#t:ShortByteString">ShortByteString</a> which provides lower overhead than <code>ByteString</code>. The bytes I was storing were really just the ASCII character set and their raison d’être was to be printed to the terminal later if the user so requested. Can <code>text-show</code> help us? Sure, it has <a href="https://hackage.haskell.org/package/text-show-3.7.1/docs/TextShow-Data-ByteString.html">a module with TextShow instance for ShortByteString</a>. Oh, but hold on. It’s not <em>quite</em> what I want!</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" data-line-number="1">[shana<span class="fu">@</span>lenalee<span class="fu">:~/</span>hakyllblog]<span class="fu">$</span> nix<span class="fu">-</span>shell <span class="fu">-</span>p <span class="ch">&#39;haskellPackages.ghcWithPackages (p: [ p.text p.bytestring p.text-show ])&#39;</span> <span class="co">--run ghci</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="dt">GHCi</span>, version <span class="fl">8.2</span><span class="fu">.</span><span class="dv">2</span><span class="fu">:</span> http<span class="fu">://</span>www<span class="fu">.</span>haskell<span class="fu">.</span>org<span class="fu">/</span>ghc<span class="fu">/</span>  <span class="fu">:?</span> for help</a>
<a class="sourceLine" id="cb1-3" data-line-number="3"><span class="dt">Prelude</span><span class="fu">&gt;</span> <span class="kw">import</span> <span class="dt">Data.Text.IO</span></a>
<a class="sourceLine" id="cb1-4" data-line-number="4"><span class="dt">Prelude</span> <span class="dt">Data.Text.IO</span><span class="fu">&gt;</span> <span class="kw">import</span> <span class="dt">Data.ByteString.Short</span></a>
<a class="sourceLine" id="cb1-5" data-line-number="5"><span class="dt">Prelude</span> <span class="dt">Data.Text.IO</span> <span class="dt">Data.ByteString.Short</span><span class="fu">&gt;</span> <span class="kw">import</span> <span class="dt">TextShow</span></a>
<a class="sourceLine" id="cb1-6" data-line-number="6"><span class="dt">Prelude</span> <span class="dt">Data.Text.IO</span> <span class="dt">Data.ByteString.Short</span> <span class="dt">TextShow</span><span class="fu">&gt;</span> <span class="kw">import</span> <span class="dt">TextShow.Data.ByteString</span></a>
<a class="sourceLine" id="cb1-7" data-line-number="7"><span class="dt">Prelude</span> <span class="dt">Data.Text.IO</span> <span class="dt">Data.ByteString.Short</span> <span class="dt">TextShow</span> <span class="dt">TextShow.Data.ByteString</span><span class="fu">&gt;</span> <span class="kw">import</span> <span class="dt">TextShow</span></a>
<a class="sourceLine" id="cb1-8" data-line-number="8"><span class="dt">Prelude</span> <span class="dt">Data.Text.IO</span> <span class="dt">Data.ByteString.Short</span> <span class="dt">TextShow</span> <span class="dt">TextShow.Data.ByteString</span><span class="fu">&gt;</span> <span class="fu">:</span>set <span class="fu">-</span><span class="dt">XOverloadedStrings</span></a>
<a class="sourceLine" id="cb1-9" data-line-number="9"><span class="dt">Prelude</span> <span class="dt">Data.Text.IO</span> <span class="dt">Data.ByteString.Short</span> <span class="dt">TextShow</span> <span class="dt">TextShow.Data.ByteString</span><span class="fu">&gt;</span> Data.Text.IO.putStrLn (showt (<span class="st">&quot;hello&quot;</span><span class="ot"> ::</span> <span class="dt">ShortByteString</span>))</a>
<a class="sourceLine" id="cb1-10" data-line-number="10"><span class="st">&quot;hello&quot;</span></a></code></pre></div>
<p>It’s printing quotes around my content. I didn’t want that. If we look at the <a href="https://hackage.haskell.org/package/text-show-3.7.1/docs/src/TextShow-Data-ByteString.html#line-89">source</a>, we can find that it defines <code>unpackChars :: ShortByteString -&gt; [Char]</code> which does exactly what we need but then the instance looks like this:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb2-1" data-line-number="1"><span class="kw">instance</span> <span class="dt">TextShow</span> <span class="dt">ShortByteString</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb2-2" data-line-number="2"> showb <span class="fu">=</span> showb <span class="fu">.</span> unpackChars</a></code></pre></div>
<p>Of course to my dismay, it does not export <code>unpackChars</code>, only the instance which is useless to me. My choice is to either copy and paste <code>unpackChars</code> into my own code or deal with it in different way such as going to <code>ByteString</code> and using a text builder function <code>ByteString -&gt; Builder</code> which doesn’t wrap with quotes and already exists.</p>
<p>To add insult to the injury, <code>unpackChars</code> actually already exists in the <code>bytestring</code> package. Worse, <code>bytestring</code> even exposes <code>.Internal</code> modules already! Sadly the author decided to not expose that. This means <code>text-show</code> had to copy and paste the implementation and subsquentely so would I until someone had the foresight to export it. At least it is <em>possible</em> to copy and paste this code because we have enough access to internal to re-implement it.</p>
<p>Another offender of “does exactly what you want but it’s inside a typeclass behind something you don’t want” that I encountered recently is <code>store</code>. <code>Store</code> instances for <code>Vector</code> are generated through TH and they store vector length followed by the data. But I already knew the length from external source and just wanted the data. Solution? Well, two:</p>
<ol type="1">
<li><p>newtype Vector passing the length through a type parameter with GHC.TypeLits or otherwise then retrieve the value in the implementation. Yuck and also slow (goes through <code>Integer</code> &amp;c.)</p></li>
<li><p>Don’t use <code>Store</code> at all. Thankfully, <code>store-core</code> exists (thank you!) which lets you work on <code>Peek</code> directly. You still have to copy <code>-ddump-splices</code> to see the generate TH then copy and paste the part you’re interested in. After adapting it a bit, I have a bunch of these things in my code for multiple vector types</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="ot">peekVectorD ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Peek</span> (<span class="dt">VU.Vector</span> <span class="dt">Double</span>)</a>
<a class="sourceLine" id="cb3-2" data-line-number="2">peekVectorD obs(<span class="dt">I</span><span class="fu">#</span> tmo) <span class="fu">=</span> <span class="dt">VUB.V_Double</span> <span class="fu">.</span> <span class="dt">VP.Vector</span> <span class="dv">0</span> obs <span class="fu">&lt;$&gt;</span> Store.peekToByteArray <span class="st">&quot;VU.Vector Double&quot;</span> blen</a>
<a class="sourceLine" id="cb3-3" data-line-number="3"><span class="kw">where</span></a>
<a class="sourceLine" id="cb3-4" data-line-number="4">  <span class="fu">!</span>blen <span class="fu">=</span> <span class="dt">I</span><span class="fu">#</span> (tmo <span class="fu">*#</span> sizeOf<span class="fu">#</span> (undefined<span class="ot"> ::</span> <span class="dt">Double</span>))</a></code></pre></div>
<p>Would be much nicer if this was generated, exported and only then used in the typclass. I understand that this is much more effort on <code>store</code> authors however so this one is more wishful thinking if anything.</p></li>
</ol>
<p>To conclude this point, please think of the users and expose non-trivial internal functions that may be useful to anyone. Stick them in <code>.Internal</code> with no guarantees, mark them INLINE if you’re relying on it, just let us use them.</p></li>
<li><p>I’m still going to get access to internals if I want to. Please don’t make me do the extra work.</p>
<p>If I need the internals and they are not expose, here are my options.</p>
<ul>
<li>Clone the package, hack the source to expose what I need, use it.</li>
<li>Ask author to do it. Wait and hope they do it and quick. In meantime, I’m probably forced to do a fork anyway.</li>
<li>Don’t do anything but simply use existing API. Cry over performance you’re losing while the code you need to go omgfast is <em>right there</em>.</li>
<li>If the function is small and self-contained, copy and paste all the code needed to make it work. Often not an option unless you want to copy whole package because likelyhood is that internals that you need are also not expose. This is basically a less drastic fork if you’re lucky, a full fork if you’re not. Downside is that it’s now your code to live with.</li>
<li>You could also complain to author that the library API is not good enough and it should do the thing you want it to do. Sometimes you may even be right! More often than not, if you’re looking for internals, it probably doesn’t belong in the API to start with and redesigning the library to include your usecase is unreasonable/impossible/not cost effective.</li>
</ul>
<p>It’s better for everyone if I can access internals. I’m happy because I get to do what I want. The author is happy because I’m not bothering him on the issue tracker and I’m talking about how fast and awesome and accessible the library is.</p></li>
<li><p>I want to use your library <em>right now</em> but it’s doing something poorly.</p>
<p>This usually warrants a fork/pull request anyway but sometimes it really may be the case that a library is doing mostly what I want but some things are poorly designed or implemented. I could workaround this on the spot and send a pull request later but if you’re not exposing internals then I’m out of luck. Either I am forced to fork it or use another library. If short on time and alternative exists, latter sounds like a better option even if the original library is much nicer in general.</p></li>
</ol>
<h3 id="about-haddock-for-.internal-modules.">About Haddock for .Internal modules.</h3>
<p>A side-point I want to mention is something that few packages like to do that I really hate. Let’s use <code>bytestring</code> as an example. Let’s look at the <a href="https://hackage.haskell.org/package/bytestring-0.10.8.2">main page for the package</a>. <code>.Internal</code> modules appear but have no documentation! Indeed often you can’t even tell that the package exposes internals. Sometimes these modules are even documented but a Haddock pragma is used to hide them.</p>
<p>Please stop doing this. It’s just a massive inconvenience. I have to first look through the cabal file to check what modules are really exposed. Then I have to source dive to see what functions are available. I have to check which are actually exported. You as an author lose the opportunity to plaster with massive letters at the top of the module that this is an internal module with no guarantees.</p>
<p>If you don’t want to document your .Internal module that’s up to you but at the very least don’t make me look through source every time I want to check something. “You’re forced to looked at source so you have to see what the functions are actually doing” is not a good argument. I probably already did and you’re not giving me any guarantees for the module anyway so there’s no need to make it a pain to actually use it.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Next time you release a library, please consider exposing internals one way or another. You can keep your usual hidden module hierarchy if you want, just make a kitchen-sink module that re-exports those. Exposing typeclasses that nearly do what one might want but not quite and not exposing the implementations also doesn’t count. If your implementation looks like</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb4-1" data-line-number="1"><span class="kw">instance</span> <span class="dt">C</span> <span class="dt">Foo</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb4-2" data-line-number="2">  someFunc <span class="fu">=</span> bar <span class="fu">.</span> someFuncImpl</a></code></pre></div>
<p>expose <code>someFuncImpl</code>.</p>
<p>Last remark is that I am not against hidden modules. I am against using them to hide useful code. You can still use hidden modules for organising your project in a way you find convenient but I would very much appreciate it if you could expose all that useful code through some means in the end.</p>
]]></summary>
</entry>
<entry>
    <title>GHC can output profiling information as JSON and you should use it.</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2018-03-02-GHC-can-output-profiles-in-JSON-format.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2018-03-02-GHC-can-output-profiles-in-JSON-format.html</id>
    <published>2018-03-02T00:00:00Z</published>
    <updated>2018-03-02T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on March  2, 2018
    
        by Fūzetsu
    
</div>

<p>This is just a small PSA. As of GHC 8.2, when <a href="http://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html#json-profile-format">GHC is able to accept <code>-pj</code> RTS flag</a> which will output things in a nice machine readable format. So, use it. I’d even be inclined to say that you should <em>always</em> use it and if you want the old format, we can have a tool that can produce that.</p>
<p>Yesterday I released two packages with relation to this. First is just a very simple and naive package that reads the output: <a href="https://hackage.haskell.org/package/ghc-prof-aeson">ghc-prof-aeson</a>. It’s just about what you’d expect, type definition then <code>aeson</code> deriving. I have thrown in Linux, OSX and Windows CI as a bonus.</p>
<p>The second package is <a href="https://hackage.haskell.org/package/ghc-prof-aeson-flamegraph">ghc-prof-aeson-flamegraph</a>. This one is similar to <a href="https://hackage.haskell.org/package/ghc-prof-flamegraph">ghc-prof-flamegraph</a> except that it doesn’t bundle FlameGraph tool and that I didn’t have to try to impose additional dependencies on the existing package. It was also not completely straight-forward to integrate with it. Primarily this package is motivated by <a href="https://github.com/fpco/ghc-prof-flamegraph/issues/10">this long-standing issue</a> where parsing the profile would just fail.</p>
<p>The <code>-p</code> and <code>-P</code> &amp;c. profiling output format is not reliable. If you’re doing retainer profiling, you now have all this extra stuff in your profile. Just use <code>-pj</code> and save everyone’s sanity.</p>
<h2 id="demo">Demo</h2>
<p>Running on a random profile I had lying around. Generated with <code>+RTS -pj</code>.</p>
<pre><code>[shana@lenalee:~/programming/ghc-prof-aeson-flamegraph]$ nix run nixpkgs.stack nixpkgs.perl.FlameGraph
[shana@lenalee:~/programming/ghc-prof-aeson-flamegraph]$ stack exec --no-nix-pure -- bash -c &#39;cat /tmp/secret.prof | ghc-prof-aeson-flamegraph | flamegraph.pl &gt; /tmp/secret.svg&#39;</code></pre>
<p>Censored to protect the innocent.</p>
<figure>
<img src="images/ghc-prof-aeson-secret.png" alt="censored_prof" /><figcaption>censored_prof</figcaption>
</figure>
<h2 id="conclusion">Conclusion</h2>
<p>You should start using <code>-pj</code> if you’re using GHC profiling. Better, you should (re)write tools to work with this format instead of the awful ad-hoc parsing that existing tools do.</p>
]]></summary>
</entry>
<entry>
    <title>My experience with NixOS</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2014-06-28-My-experience-with-NixOS.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2014-06-28-My-experience-with-NixOS.html</id>
    <published>2014-06-28T08:14:30Z</published>
    <updated>2014-06-28T08:14:30Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on June 28, 2014
    
        by Fūzetsu
    
</div>

<p>This post is for Haskellers interested in nix (the package manager) and maybe even NixOS (a distribution built on nix). If you’re not interested then skip it, but I know many people are. It describes how I made the switch and some of my experiences since. I have put off this blog post for a long time, hoping to write it up once I have everything working just like I want it but I was finally motivated to write it up by people expressing interest on IRC. I know many people want to switch but aren’t quite there yet, hopefully this can help them make the decision. If you’re interested in nix but not NixOS, you probably want to just skim the beginning.</p>
<p>Please note that things contained here are just my opinions and I’m not some NixOS guru so things stated here may well be inaccurate.</p>
<p>A couple of weeks ago I have switched to NixOS. Like many, I have seen <a href="http://ocharles.org.uk/blog/posts/2014-02-04-how-i-develop-with-nixos.html">the blogpost by ocharles</a> and have since thought ‘It’d be great to switch but I’d hate to put in the effort’ but the thought crept in. I ask that you read that blog post first. I have even started to set up NixOS on a separate hard-drive. Recently I have finally decided to retire my trusty ThinkPad X61s on which I did my hacking for the past three years: it was overheating, had holes through it (don’t ask), falling apart and I have took it apart so many times that it’s a miracle it even stayed together. This was a perfect chance. I have taken out the SSD (which cost me more than the netbook itself) and repurposed one of my fileservers which was running Gentoo into a desktop machine.</p>
<p>Probably the most vital resource when making the switch is the NixOS is the <a href="http://nixos.org/nixos/manual/">NixOS manual</a>. I’ll not go over the installation process but you can find my configuration file <a href="https://github.com/Fuuzetsu/nix-project-defaults/blob/master/nixos-config/configuration.nix">here</a>.</p>
<p>My current set-up is XMonad without a DE, using SLiM as a log-in DM.</p>
<p>At the beginning I struggled. I had problems understanding how things worked and some software I wanted to use was simply not packaged. I spent the first couple of weeks with KDE and without some software I wanted. This is a bit of a downside: the number of packages is not the greatest of all distributions. Please don’t get me wrong, there <em>is</em> a lot of software already but the chances are that if you’re using something not that common, you might have to package it yourself. The upside is, it’s easy to do.</p>
<p>I will briefly describe some things which will related to Haskell development later. There is a thing called <a href="https://nixos.org/hydra/">Hydra</a>, it’s a build-bot that NixOS uses. There is a thing called <a href="https://github.com/NixOS/nixpkgs">nixpkgs</a>, it is a repository of packages used by NixOS and also nix itself if you aren’t going for the full OS. nixpkgs is essentially a big repository of nix expressions. Hydra looks at this and builds the expressions, resulting in packages. Main re-distribution works in channels: a user subscribes to a channel and when we ask for some package to be installed, this is where the information is taken from. Official channels are effectively nixpkgs at some commit: nixos channel might be a few weeks behind nixpkgs HEAD, nixos-unstable is usually a few days. Channels are updated when Hydra finishes to build a particular jobset: this means you get binaries for the default settings of all Hydra-built packages. This includes Haskell packages!</p>
<p>I will now describe how I have been doing Haskell development. Again, note that this is constantly evolving while I discover new things.</p>
<h1 id="haskell-development-with-nixnixos">Haskell development with nix/NixOS</h1>
<p>Firstly, NixOS is not necessary to benefit. Pretty much everything I say here is due to nix itself.</p>
<p>Perhaps the main motivation for using nix is wanting to avoid cabal hell. The presence of cabal sandboxes and freezing of dependencies has allowed many people to avoid the problem. I myself used sandboxes very soon after they came out and use cabal-dev before that. My main problem with sandboxes is managing them: are you sandboxing a new project? Come back in an hour when text, hxt, lens, attoparsec, haskell-src-exts and whatever else you happen to be using have compiled for the 50th time on your machine. Sure, one can use shared sandboxes but it is a <em>massive</em> pain. I have wasted hours of my life recompiling same dependencies. nix allows you to avoid this.</p>
<p>I will consider a few scenarios and any potential problems that might come up and how I have dealt (or not dealt!) with them so far.</p>
<p>You have your project. Perhaps the first thing you do is write the cabal file or maybe you already have one but you want to use nix. When we develop, we often want to actually be able to be in the environment of the package, be able to run ghci and all that jazz. There’s a tool called <code>nix-shell</code> which can help you. This effectivelly allows you drop into a sandbox of your project. This is the magical thing <a href="http://ocharles.org.uk/blog/posts/2014-02-04-how-i-develop-with-nixos.html">ocharles refered to in his blog post</a>. What he did not mention is that you can generate on of these expressions necessary to use <code>nix-shell</code>. Here’s a real example:</p>
<pre><code>[shana@lenalee:/tmp]$ cat Yukari.cabal
name:                Yukari
version:             0.1.0.0
synopsis:            Command line program that allows for automation of various tasks on the AnimeBytes private tracker website.
homepage:            http://github.com/Fuuzetsu/yukari
license:             GPL-3

license-file:        LICENSE

author:              Mateusz Kowalczyk
maintainer:          fuuzetsu@fuuzetsu.co.uk
category:            Utils
build-type:          Simple
cabal-version:       &gt;=1.8

executable yukari
  main-is:             src/Main.hs
  build-depends:       base ==4.*, Yukari

library
  default-language:     Haskell2010

  build-depends:       base ==4.*, curl ==1.3.*, HTTP ==4000.*, filepath ==1.3.*
                       , directory ==1.2.*, bytestring ==0.10.*, network ==2.5.*
                       , text ==1.1.1.*, attoparsec ==0.12.*, HandsomeSoup ==0.3.*
                       , hxt ==9.*, download-curl ==0.1.*, dyre

  hs-source-dirs:       src
  exposed-modules:
    Utils.Yukari
    Utils.Yukari.Crawler
    Utils.Yukari.Filters
    Utils.Yukari.Formatter
    Utils.Yukari.Parser
    Utils.Yukari.Settings
    Utils.Yukari.Spender
    Utils.Yukari.Types

test-suite spec
  type:             exitcode-stdio-1.0
  default-language: Haskell2010
  main-is:          Spec.hs
  hs-source-dirs:
      test

  build-depends:       base ==4.*, Yukari, hspec, QuickCheck == 2.*,
                       filepath==1.3.*, directory ==1.2.*</code></pre>
<p>Then with little help of cabal2nix (the dummy sha256 parameter is a hack here as we’re generating an expression for a source repository).:</p>
<pre><code>[shana@lenalee:/tmp]$ cabal2nix Yukari.cabal --sha256 foo
{ cabal, attoparsec, curl, downloadCurl, dyre, filepath
, HandsomeSoup, hspec, HTTP, hxt, network, QuickCheck, text
}:

cabal.mkDerivation (self: {
  pname = &quot;Yukari&quot;;
  version = &quot;0.1.0.0&quot;;
  sha256 = &quot;foo&quot;;
  isLibrary = true;
  isExecutable = true;
  buildDepends = [
    attoparsec curl downloadCurl dyre filepath HandsomeSoup HTTP hxt
    network text
  ];
  testDepends = [ filepath hspec QuickCheck ];
  meta = {
    homepage = &quot;http://github.com/Fuuzetsu/yukari&quot;;
    description = &quot;Command line program that allows for automation of various tasks on the AnimeBytes private tracker website&quot;;
    license = self.stdenv.lib.licenses.gpl3;
    platforms = self.ghc.meta.platforms;
  };
})</code></pre>
<p>Note that <code>cabal2nix</code> generates expressions suitable for nixpkgs. To use it for a shell environment, I ammend the resulting expression into following:</p>
<pre><code>{ pkgs ? (import &lt;nixpkgs&gt; {})
, haskellPackages ? pkgs.haskellPackages_ghc763
}:

haskellPackages.cabal.mkDerivation (self: {
  pname = &quot;Yukari&quot;;
  version = &quot;0.1.0.0&quot;;
  src = /home/shana/programming/yukari;
  isLibrary = true;
  isExecutable = true;
  buildDepends = with haskellPackages; [
    attoparsec curl downloadCurl dyre filepath HandsomeSoup HTTP hxt
    network text
  ];
  testDepends = with haskellPackages; [ filepath hspec QuickCheck ];
  meta = {
    homepage = &quot;http://github.com/Fuuzetsu/yukari&quot;;
    description = &quot;Command line program that allows for automation of various tasks on the AnimeBytes private tracker website&quot;;
    license = self.stdenv.lib.licenses.gpl3;
    platforms = self.ghc.meta.platforms;
  };
})</code></pre>
<p>If at any point I want to use a different compiler version, I only have to change it at the top (or use a flag to nix-shell) and it will automagically all just work. Now I can use this sandbox:</p>
<pre><code>[shana@lenalee:~/programming/yukari]$ nix-shell --pure

[nix-shell:~/programming/yukari]$ cat .ghci
:set -isrc -fbreak-on-error
[nix-shell:~/programming/yukari]$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
package flags have changed, resetting and loading new packages...
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package filepath-1.3.0.1 ... linking ... done.
Loading package old-locale-1.0.0.5 ... linking ... done.
Loading package time-1.4.0.1 ... linking ... done.
Loading package bytestring-0.10.0.2 ... linking ... done.
Loading package unix-2.6.0.1 ... linking ... done.
Loading package directory-1.2.0.1 ... linking ... done.
Loading package old-time-1.1.0.1 ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package process-1.1.0.2 ... linking ... done.
Loading package Cabal-1.16.0 ... linking ... done.
Loading package binary-0.5.1.1 ... linking ... done.
Loading package bin-package-db-0.0.0.0 ... linking ... done.
Loading package hoopl-3.9.0.0 ... linking ... done.
Loading package hpc-0.6.0.0 ... linking ... done.
Loading package template-haskell ... linking ... done.
Loading package ghc-7.6.3 ... linking ... done.
Prelude&gt; :l  Utils.Yukari
[1 of 7] Compiling Utils.Yukari.Types ( src/Utils/Yukari/Types.hs, interpreted )
[2 of 7] Compiling Utils.Yukari.Settings ( src/Utils/Yukari/Settings.hs, interpreted )
[3 of 7] Compiling Utils.Yukari.Parser ( src/Utils/Yukari/Parser.hs, interpreted )
[4 of 7] Compiling Utils.Yukari.Formatter ( src/Utils/Yukari/Formatter.hs, interpreted )
[5 of 7] Compiling Utils.Yukari.Crawler ( src/Utils/Yukari/Crawler.hs, interpreted )
[6 of 7] Compiling Utils.Yukari.Spender ( src/Utils/Yukari/Spender.hs, interpreted )
[7 of 7] Compiling Utils.Yukari     ( src/Utils/Yukari.hs, interpreted )
Ok, modules loaded: Utils.Yukari, Utils.Yukari.Crawler, Utils.Yukari.Formatter, Utils.Yukari.Settings, Utils.Yukari.Spender, Utils.Yukari.Parser, Utils.Yukari.Types.</code></pre>
<p>The <code>--pure</code> stops any ‘globally’ installed tools or packages from polluting the environment which ensures that we only use what we say we do: no surprises because other developer didn’t have ‘somespecialprogram’ installed! Personally I currently use emacs with haskell-mode and I want a REPL in emacs. nix-shell lets you do this. The way I do it is to eval <code>(setq haskell-program-name &quot;nix-repl --pure --command &quot;ghci&quot;)</code>.</p>
<p>So we managed to sandbox a single project. Cool, but what about if we want to depend on another project? It’s often the case that our project depends on another of our projects which might not be on Hackage or we want to work against dev version or ….</p>
<p>I do this with Haddock: we recently split out haddock parser into a sub-library, ‘haddock-library’. I simply wrote an expression for haddock-library and then import it from haddock expression. Simple:</p>
<pre><code>[shana@lenalee:~/programming/haddock]$ cat default.nix
{ haskellPackages ? (import &lt;nixpkgs&gt; {}).myHaskellPackages_ghcHEAD
, haddockLibrary ? (import /home/shana/programming/haddock/haddock-library
    { haskellPackages = haskellPackages; })
}:

haskellPackages.cabal.mkDerivation (self: {
  pname = &quot;haddock&quot;;
  version = &quot;2.15.0&quot;;
  src = /home/shana/programming/haddock;
  buildDepends = with haskellPackages;
                   [ Cabal deepseq filepath ghcPaths xhtml haddockLibrary ];
  testDepends = with haskellPackages; [ Cabal deepseq filepath hspec QuickCheck ];
  isLibrary = true;
  isExecutable = true;
  enableSplitObjs = false;
  noHaddock = true;
  doCheck = true;
})
[shana@lenalee:~/programming/haddock]$ cat haddock-library/default.nix
{ haskellPackages ? (import &lt;nixpkgs&gt; {}).myHaskellPackages_ghc763
}:
let
  inherit (haskellPackages) cabal deepseq QuickCheck hspec baseCompat;
in
cabal.mkDerivation (self: {
  pname = &quot;haddock-library&quot;;
  version = &quot;1.1.0&quot;;
  src = /home/shana/programming/haddock/haddock-library;
  testDepends = [ QuickCheck hspec baseCompat ];
  buildDepends = [ deepseq ];
  isLibrary = true;
  isExecutable = false;
  enableSplitObjs = false;
  doCheck = true;
})</code></pre>
<p>There are a couple of things going on here. Firstly, you can see that haddock-library by default uses GHC 7.6.3: <code>haskellPackages ? (import &lt;nixpkgs&gt; {}).myHaskellPackages_ghc763</code>. This is fine but when I’m working with Haddock itself, I want to make sure this gets built with same version as haddock, so I have</p>
<pre><code>, haddockLibrary ? (import /home/shana/programming/haddock/haddock-library
    { haskellPackages = haskellPackages; })</code></pre>
<p>This makes sure we use the same set of packages in both so when <code>haddock</code> uses GHC HEAD then so does <code>haddock-library</code>. To nix enthusiasts out there, I’m aware I can use ‘inhert’, just didn’t get around to it.</p>
<p>Now whenever I change things under haddock-library and drop into haddock shell, it will automagically get rebuilt.</p>
<p>Better yet, I do this with GHC itself! If you’ll notice, I’m importing <code>(import &lt;nixpkgs&gt; {}).myHaskellPackages_ghcHEAD</code>. If you look in my <a href="https://github.com/Fuuzetsu/nix-project-defaults/blob/master/nixpkgs-config/config.nix">nixpkgs config</a> you’ll find some incantations of following nature:</p>
<pre><code>{ pkgs }:

{ packageOverrides = self: with pkgs; rec {

  haskellPackages_ghcHEAD = self.haskell.packages {
    ghcPath = /home/shana/programming/ghc;
    ghcBinary = self.haskellPackages.ghcPlain;
    prefFun = self.haskell.ghcHEADPrefs;
  };

  …</code></pre>
<p>What’s going on here? Well, a few things. First I’m overwriting a thing called <code>ghcPath</code> to <code>/home/shana/programming/ghc</code>. This points to my local GHC HEAD checkout. In there I have another nix expression which describes how to build GHC HEAD. This means that yes, I am able to have Haddock depend on a checkout of GHC itself. Here is that GHC expression in full:</p>
<pre><code>{ pkgs ? (import &lt;nixpkgs&gt; {})
, stdenv ? pkgs.stdenv
, ghc ? pkgs.ghc.ghc782
, perl ? pkgs.perl
, gmp ? pkgs.gmp
, ncurses ? pkgs.ncurses
, happy ? pkgs.haskellPackages.happy
, alex ? pkgs.haskellPackages.alex
, automake ? pkgs.automake
, autoconf ? pkgs.autoconf
, git ? pkgs.git
, libxslt ? pkgs.libxslt
, libxml2 ? pkgs.libxml2
, python ? pkgs.python
}:

stdenv.mkDerivation rec {
  name = &quot;ghc-${version}&quot;;
  version = &quot;7.9.20140624&quot;;

  src = &quot;/home/shana/programming/ghc&quot;;

  buildInputs = [ ghc perl gmp ncurses automake autoconf
                  git happy alex libxslt libxml2 python ];

  enableParallelBuilding = true;

  buildMK = &#39;&#39;
    libraries/integer-gmp_CONFIGURE_OPTS += --configure-option=--with-gmp-libraries=&quot;${gmp}/lib&quot;
    libraries/integer-gmp_CONFIGURE_OPTS += --configure-option=--with-gmp-includes=&quot;${gmp}/include&quot;
    DYNAMIC_BY_DEFAULT = NO
    BuildFlavour = quick
  &#39;&#39;;

  preConfigure = &#39;&#39;
    echo &quot;${buildMK}&quot; &gt; mk/build.mk
    perl boot
    sed -i -e &#39;s|-isysroot /Developer/SDKs/MacOSX10.5.sdk||&#39; configure
  &#39;&#39; + stdenv.lib.optionalString (!stdenv.isDarwin) &#39;&#39;
    export NIX_LDFLAGS=&quot;$NIX_LDFLAGS -rpath $out/lib/ghc-${version}&quot;
  &#39;&#39;;

  configureFlags = &quot;--with-gcc=${stdenv.gcc}/bin/gcc&quot;;

  # required, because otherwise all symbols from HSffi.o are stripped, and
  # that in turn causes GHCi to abort
  stripDebugFlags = [ &quot;-S&quot; &quot;--keep-file-symbols&quot; ];

  meta = {
    homepage = &quot;http://haskell.org/ghc&quot;;
    description = &quot;The Glasgow Haskell Compiler&quot;;
    maintainers = [
      stdenv.lib.maintainers.marcweber
      stdenv.lib.maintainers.andres
      stdenv.lib.maintainers.simons
    ];
    inherit (ghc.meta) license platforms;
  };</code></pre>
<p>You don’t have to be able to understand this but know that whenever I want to update my GHC HEAD, all I have to do is to update the repository (through usual sync-all GHC script) and then bump up the version in above expression. Now if I go to drop into a <code>nix-shell</code> for Haddock, it will notice the change and build GHC HEAD.</p>
<p>Now to explain another bit of my config:</p>
<pre><code>  myHaskellPackages_ghcHEAD = pkgs.recurseIntoAttrs (haskellPackages_ghcHEAD.override {
    extension = se : su : {
      syb = se.callPackage /home/shana/programming/nixpkgs/pkgs/development/libraries/haskell/syb/0.4.2.nix {};
      vty_5_1_0 = se.callPackage /home/shana/programming/nix-project-defaults/vty/5.1.0.nix {};
      mtl = se.callPackage /home/shana/programming/nix-project-defaults/mtl/2.2.1.nix {};
      testFrameworkSmallcheck =
        se.callPackage /home/shana/programming/nix-project-defaults/test-framework-smallcheck {};
    };
  });

  …
}; }</code></pre>
<p>What I’m doing here is defining or overwriting packages in the Haskell package set: as you can see, I’m defining vty_5_1_0 and setting mtl default to 2.2.1. Why? They were either not at that moment in my version of nixpkgs (my channel hasn’t caught up) or I wanted to use different defaults. It’s as easy as the above. This brings me to the next point.</p>
<p>What happens when nixpkgs doesn’t have something you need?</p>
<ol type="1">
<li><p>Create an expression for it. This is as easy as using cabal2nix. If it’s on hackage, it’s even easier:</p>
<pre><code>[shana@lenalee:~/programming/haddock]$ cabal2nix cabal://text
{ cabal, deepseq, HUnit, QuickCheck, random, testFramework
, testFrameworkHunit, testFrameworkQuickcheck2
}:

cabal.mkDerivation (self: {
  pname = &quot;text&quot;;
  version = &quot;1.1.1.3&quot;;
  sha256 = &quot;1yrzg449nbbzh2fb9mdmf2jjfhk2g87kr9m2ibssbsqx53p98z0c&quot;;
  buildDepends = [ deepseq ];
  testDepends = [
    deepseq HUnit QuickCheck random testFramework testFrameworkHunit
    testFrameworkQuickcheck2
  ];
  meta = {
    homepage = &quot;https://github.com/bos/text&quot;;
    description = &quot;An efficient packed Unicode text type&quot;;
    license = self.stdenv.lib.licenses.bsd3;
    platforms = self.ghc.meta.platforms;
  };
})</code></pre></li>
<li><p>Point to it somehow from your project. Two main ways are to either add it to your package base (as seen in my config snippet) or do it directly from a project (as seen from my haddock expression snippet).</p></li>
<li><p>Make a pull request to <a href="https://github.com/NixOS/nixpkgs">nixpkgs</a> so everyone can benefit. Please read <a href="https://nixos.org/wiki/Contributing">contribution</a> NixOS wiki page on how to contribute.</p></li>
</ol>
<p>So is this better than cabal sandbox? In my opinion, yes, here’s why I think so:</p>
<ul>
<li><p>Automatically share binary results: are you working with dev version of a library? After you build it once, all your other projects benefit: nix will not rebuild a dependency ‘just because’, it will re-use the binary across all your projects that say they want it! This is already much better than sandboxes where you have to explicitly share.</p></li>
<li><p>You can specify more than Haskell packages: cabal only allows you to specify Haskell dependencies but what if you require gcc too? Maybe you have development tools like ghc-mod that you want to use. When I wanted to use ghc-mod across projects with multiple GHC versions it was absolute nightmare. nix will let you do this effortlessly be it with Haskell packages or external tools or even Haskell tools which depend on specific versions of GHC. Remember, we can sandbox GHC versions and the tools depending on them.</p></li>
<li><p>It’s not limited to Haskell software. You can sandbox just about anything you can imagine. You absolutely have to run some PHP script? Sure, if it’s a bit complicated then write a nix expression for it and run. If it’s simple, <code>nix-shell -p php</code> will drop you in a shell with PHP available, automatically pulling in all dependencies. Once you’re done with that environment, no longer dependencies will be removed during garbage collection.</p></li>
<li><p>Uses binaries whenever available while cabal sandbox will usually leave you waiting for everything to compile.</p></li>
</ul>
<p>Even <code>hakyll</code> which is a Haskell program that will generate a page from this Markdown post is going to be used by <code>nix-shell -p haskellPackages_ghc763.ghc -p haskellPackages_ghc763.hakyll --pure</code>: I don’t need it day to day so I’ll just let it get garbage collected at next opportunity.</p>
<p>The downsides of using nix-shell for Haskell projects:</p>
<ul>
<li><p>It’s a less-documented process. For more complicated setups, it might take a bit of figuring out how to get it to work. An example is me trying to figure out how to get Yi to see its own available libraries at runtime which is required for dynamic reloading &amp;c.</p></li>
<li><p>The workflow is a bit different from what you might be used to. Currently I’m using <code>eval &quot;$configurePhase&quot; &amp;&amp; eval &quot;$buildPhase&quot;</code> in my projects which behind the scenes runs cabal. Note that there are people who use nix and stick with their usual development workflow of using cabal configure/build themselves so it is</p></li>
<li><p>Rarely it might be necessary to run cabal by hand if your project requires it. My use-case was generating symbols that we get from cabal such as those used by CPP library version pragmas. This is not too common however.</p></li>
<li><p>There are two places to update when you add/remove dependencies to the project: nix expression and cabal file. I consider this very minor considering it’s probably a word change in each. To be clear, your cabal projects keep their cabal files, using nix does not mean that yourproject.cabal is no longer used.</p></li>
</ul>
<h1 id="summary">Summary</h1>
<p>I’ll give a breakdown of what I like and dislike about nix and NixOS so far.</p>
<p>What I like:</p>
<ul>
<li><p>NixOS configuration is a pleasure. You no longer have to run around all over your system in hunt of configuration files, you now have a config file that you yourself decide how to split up (if at all) and if you screw anything up, you can always roll back.</p></li>
<li><p>Packaging software is fairly easy. There <em>are</em> things that are difficult to package but in huge majority of cases, it is a few lines. It’s not terribly difficult to get started.</p></li>
<li><p>Binaries for Haskell packages that aren’t terribly out of date. Many binary distros out there have outdated Haskell packages if at all. Here there are tools to generate expressions from cabal files so updating is not a chore. If all you’re doing is a version bump then it’s as easy as changing a line or two and making a pull request. Hydra is nearly always churning through new Haskell packages to make sure it’s all up to date with change dependencies.</p></li>
<li><p>I’m not losing sleep over possibility of cabal hell.</p></li>
<li><p>I’m not losing days of my life staring at lens or text build.</p></li>
<li><p>Switching between GHC versions is trivial. In the past I was switching symlinks between GHC versions and carefully sandboxing everything. While it worked for development, it certainly did not work for anything using currently-active package databases (ghc-mod anyone?).</p></li>
<li><p>I don’t have to think about things clashing. If one project wants text-0.11, another -1.0 and another -dev999999Ijustmadeachange then there’s no real hassle on my part.</p></li>
<li><p>Easy deployment. If you’re a company, you can set up Hydra to build your software for you. If you’re a sysadmin, you can install nix and your users are able to install they software they want without bothering you: nix allows regular users to install software into their profile.</p></li>
<li><p>You can roll-back through upgrades whether it be system upgrades or user profile upgrades. Every time you run <code>nix-env -i</code> to install a package, a new generation is created so you can roll-back later if you need to.</p></li>
</ul>
<p>What I dislike:</p>
<ul>
<li><p>The documentation is a bit scarce. I end up having to look through package or NixOS module sources more than I’d like to.</p></li>
<li><p>The nix expression language is not statically typed yet and error messages are often complete ass.</p></li>
<li><p>On more popular distros, often one can use search engines to find people who already had the problem. On NixOS such information sometimes just does not exist. I have been relentlessly posting to the nix mailing list to hopefully change this a bit and to actually find out what I wanted.</p></li>
<li><p>One has to either disallow unfree packages completely or allow them. It’s not possible to say that we’re OK with pulling in unfree nvidia drivers but other than that we want nothing unfree on our system.</p></li>
<li><p>I’m used to being able to customise each software package in 50 different ways. Often in nixpkgs the package maintainers don’t take time to expose various options. To follow up, Hydra only builds packages with the default flags. The current hack is to define multiple packages with different default flags.</p></li>
<li><p>Pull requests in certain areas can take a longer time and/or some reminding before getting merged. Haskell-related PRs get merged quickly however.</p></li>
<li><p>The package managment tools are not as up to scratch as they are on older distributions. Gentoo has some great tooling. I put it towards young age of the distribution.</p></li>
<li><p>Getting fixes from nixpkgs newer than your channel is a bit of a pain. You either check out the appropriate commit and apply patches on top or rebuild half of your system. I used to run against HEAD version of nixpkgs and found myself compiling a lot of stuff because Hydra didn’t build it yet. I recommend nixos-unstable channel which is usually not far behind HEAD.</p></li>
<li><p>systemd</p></li>
<li><p>There’s a policy to only keep latest versions of software around unless it’s necessary to have more. This means that when you generate a nix expression from cabal file, it will try to use the defaults in nixpkgs rather than specific versions. While I dislike this quite a bit, there are a few things that can be done to keep things sane:</p>
<ul>
<li><p>When you really need an older version, you can explicitly refer to it if in nixpkgs or refer to your local expression if it isn’t in nixpkgs</p></li>
<li><p>If the package works with a newer version and it’s just the case of a bump in cabal file, you can set ‘jailbreak = true’ which ignores what cabal says about versions.</p></li>
<li><p>Many Haskell packages already have multiple versions available so I find that in practice it is not a huge worry anyway. I initially feared (and still do a bit) a horrible version mess but it seems to well enough.</p></li>
</ul></li>
<li><p>There are no binaries yet for 7.8.2 of package versions which means if you use those, you’ll have to wait a bit while they build just like you would have to with cabal install anyway. This is only temporary but might be a slight annoyance if you’re expecting binaries for those. I think building binaries for 7.8 will be switched on with 7.8.3 out but this is speculation.</p></li>
<li><p>It can be a bit disk-space heavy because we potentially hold onto many versions of the same package, just built with different dependencies. The two ways to save space are: optimise your store which uses hardlinks for identical files to save space (saves GBs) and garbage-collect which removes software that is no longer dependended on. Even after you say that you no longer want some software with <code>nix-env -e</code>, it stays on your system until garbage-collected.</p></li>
</ul>
<p>It may look like there are many dislikes but they are mostly annoyances or my incompetence. I definitely would recommend nix or even NixOS if you are already considering a switch. I have to say that I can not recommend switching to NixOS if you need your machine in development-ready mode next morning because it can take a few days to get everything going just the way you need it. I don’t have this worry with nix itself however which you can install alongside your distro. If you’re a working man, I believe you could set up NixOS in a VM first and then simply carry over the config when you have everything ready.</p>
<p>In general I find that I never worry whether my package database will screw up or anything like that.</p>
<p>If you’re interested, please swing by #nixos on Freenode. This and the mailing list is the majority of my help has been coming from.</p>
<p>It’s a bit of a hectic post so please feel free to <a href="/contact.html">contact me</a> if you have questions and I’ll try to answer to best of my knowledge. Note that I’ll almost certainly not see and/or not reply to questions on reddit if this is to find its way there, sorry.</p>
]]></summary>
</entry>
<entry>
    <title>Haddock 2.14.2</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2014-04-02-Haddock-2.14.2.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2014-04-02-Haddock-2.14.2.html</id>
    <published>2014-04-02T23:03:20Z</published>
    <updated>2014-04-02T23:03:20Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on April  2, 2014
    
        by Fūzetsu
    
</div>

<p>This is just a quick follow-up to my previous post. We have now released Haddock 2.14.2 which contains few minor changes. The reason for this release is to get a few quick patches in. No fancy overview today, just quick mentions. Here is the relevant part of the changelog:</p>
<p>Changes in version 2.14.2</p>
<ul>
<li><p>Always drop –split-objs GHC flag for performance reasons <a href="http://trac.haskell.org/haddock/ticket/292">(#292)</a></p></li>
<li><p>Print kind signatures GADTs <a href="http://trac.haskell.org/haddock/ticket/85">(#85)</a></p></li>
<li><p>Drop single leading whitespace when reasonable from @-style blocks <a href="http://trac.haskell.org/haddock/ticket/201">(#201)</a></p></li>
<li><p>Fix crashes associated with exporting data family record selectors <a href="http://trac.haskell.org/haddock/ticket/294">(#294)</a></p></li>
</ul>
<p><a href="http://trac.haskell.org/haddock/ticket/201">#201</a> was the the annoying aesthetics bug I mentioned last time and that is now fixed.</p>
<p><a href="http://trac.haskell.org/haddock/ticket/294">#294</a> was a bug we’re glad to have gotten rid of now: it was only reported recently but I imagine more and more projects would have start to hit it.</p>
<p><a href="http://trac.haskell.org/haddock/ticket/292">#292</a> should improve performance considerably in some special cases, such as when Template Haskell is being used.</p>
<p><a href="http://trac.haskell.org/haddock/ticket/85">#85</a> was just a quick resolution of years old ticket, I think you’ll find it useful.</p>
<p>I predict that this is the version that will ship with GHC 7.8.1 and I don’t think we’ll have any more 2.14.x releases.</p>
<p>Ideally I’d like to get well under 100 open tickets for the next release (there are currently 117 open).</p>
<p>Some things I will be concentrating on next is splitting up Haddock into a few packages and working on the Hoogle back-end. The Hoogle back-end is incredibly broken which is a shame considering Hoogle is a very useful service. We want to make the maintainers life easier.</p>
<p>Splitting up Haddock into a few packages will be of great advantage to people wishing to use (parts of) Haddock as a library without adding a dependency on a specific version of GHC to their program. It should also become much easier to implement and maintain your own back-ends.</p>
<p>If you are interested in helping out with Haddock, we’d love to have you. Pop into #haddock on Freenode, make some noise and wait for someone to respond. Alternatively, <a href="/contact.html">contact me</a> through other means.</p>
<p>PS: While I realise that some of my posts make it on reddit, I myself do not use it. You’re welcome to discuss these but if you leave questions or messages to me on reddit, I will almost certainly not see them. If you want my attention, please either use e-mail or IRC. Thanks!</p>
]]></summary>
</entry>
<entry>
    <title>New Haddock released! A visual guide to changes.</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2014-03-24-New-Haddock-released%21-A-visual-guide-to-changes.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2014-03-24-New-Haddock-released%21-A-visual-guide-to-changes.html</id>
    <published>2014-03-24T15:33:16Z</published>
    <updated>2014-03-24T15:33:16Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on March 24, 2014
    
        by Fūzetsu
    
</div>

<p>We’ve just uploaded <a href="http://hackage.haskell.org/package/haddock-2.14.1">Haddock 2.14.1</a> and while you can view the <a href="http://www.haskell.org/haddock/CHANGES.txt">CHANGES</a> file, here I’ll attempt to present all new features added since 2.13.2.1. A quick note that while 2.14.0 is in the <a href="http://www.haskell.org/haddock/CHANGES.txt">CHANGES</a> file, it was never officially released to the public. Consider it an internal release if you will. This basically covers 2.14.0 and 2.14.1. I am posting this now as I hear GHC 7.8.1 is supposed to come out in a few hours and this is the version that you’ll be getting. I had only just realised this but this integrates the changes I have made over the last GSoC into a stable GHC release. FYI, I’m using GHC 7.8-rc2 for any code snippets presented here. Last thing to mention is that any ticket numbers you see here are the tickets as seen on <a href="http://trac.haskell.org/haddock/">Haddock Trac</a>. We’re actually planning to move everything to GitHub soon so keep that in mind if you’re reading this further in the future. Note that pretty much everything here is described in <a href="http://www.haskell.org/haddock/doc/html/index.html">Haddock documentation</a> (although without nice examples) so please refer to that if you need further information.</p>
<p>Let’s begin!</p>
<ul>
<li><p>Print entities with missing documentation (#258)</p>
<p>This adds a <code>--print-missing-docs</code> flag to Haddock. Given a file like this:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">module</span> <span class="dt">Foo</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"></a>
<a class="sourceLine" id="cb1-3" data-line-number="3"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb1-4" data-line-number="4">f <span class="fu">=</span> ()</a>
<a class="sourceLine" id="cb1-5" data-line-number="5"></a>
<a class="sourceLine" id="cb1-6" data-line-number="6"><span class="co">-- | Doc for &#39;g&#39;</span></a>
<a class="sourceLine" id="cb1-7" data-line-number="7"><span class="ot">g ::</span> ()</a>
<a class="sourceLine" id="cb1-8" data-line-number="8">g <span class="fu">=</span> ()</a>
<a class="sourceLine" id="cb1-9" data-line-number="9"></a>
<a class="sourceLine" id="cb1-10" data-line-number="10"><span class="kw">class</span> <span class="dt">FooClass</span> a <span class="kw">where</span></a></code></pre></div>
<p>we can ask Haddock to tell us which docs are missing:</p>
<pre><code>$ haddock Foo.hs -h -o /tmp --print-missing-docs
Haddock coverage:
  25% (  1 /  4) in &#39;Foo&#39;
  Missing documentation for:
    Module header
    f (Foo.hs:3)
    FooClass (Foo.hs:10)</code></pre>
<p>There has been a suggestion to make this flag default. I’m personally not against it. What do you think?</p></li>
<li><p>Print a warning message when given <code>-optghc</code> instead of <code>--optghc</code> (#5)</p>
<p>This is just a quick fix to a long-standing feature request. The problem was that <code>-optghc</code> actually means <code>--odir=ptghc</code> which is probably not what you wanted. We now warn when we see <code>-optghc</code> in the flags. The warning is:</p>
<p><code>Warning: `-optghc' means `-o ptghc', did you mean `--optghc'?</code></p></li>
<li><p>Add <code>--compatible-interface-versions</code> (#231)</p>
<p>This simply prints the versions of the .haddock interface files that your Haddock binary knows how to work with.</p>
<pre><code>$ haddock --compatible-interface-versions
25</code></pre>
<p>We had some fairly big changes to the interface file so current Haddock can only work with a single version: this means it can’t re-use .haddock files that your previous versions might have generated.</p></li>
<li><p>Allow to generate latex documentation for FFI declarations (#247)</p>
<p>Fairly self-explanatory. Note that I don’t encourage actually trying to use the LaTeX back-end, it is not maintained and has many bugs. It is meant to serve a sole purpose of generating the Haskell Report when that time comes. If you are interested in using this back-end and are willing to put in some time to breathe some life into it, we’d love to have you, contact us!</p></li>
<li><p>Add copyright and license information to generated documentation</p>
<p>We let you document modules with a comment containing some special fields. The header is documented <a href="http://www.haskell.org/haddock/doc/html/ch03s03.html">here</a>. Consider the following module:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb4-1" data-line-number="1"><span class="co">{-|</span></a>
<a class="sourceLine" id="cb4-2" data-line-number="2"><span class="co">Module      : W</span></a>
<a class="sourceLine" id="cb4-3" data-line-number="3"><span class="co">Description : Short description</span></a>
<a class="sourceLine" id="cb4-4" data-line-number="4"><span class="co">Copyright   : (c) Some Guy, 2013</span></a>
<a class="sourceLine" id="cb4-5" data-line-number="5"><span class="co">                  Someone Else, 2014</span></a>
<a class="sourceLine" id="cb4-6" data-line-number="6"><span class="co">License     : GPL-3</span></a>
<a class="sourceLine" id="cb4-7" data-line-number="7"><span class="co">Maintainer  : sample@email.com</span></a>
<a class="sourceLine" id="cb4-8" data-line-number="8"><span class="co">Stability   : experimental</span></a>
<a class="sourceLine" id="cb4-9" data-line-number="9"><span class="co">Portability : POSIX</span></a>
<a class="sourceLine" id="cb4-10" data-line-number="10"></a>
<a class="sourceLine" id="cb4-11" data-line-number="11"><span class="co">Here is a longer description of this module, containing some</span></a>
<a class="sourceLine" id="cb4-12" data-line-number="12"><span class="co">commentary with @some markup@.</span></a>
<a class="sourceLine" id="cb4-13" data-line-number="13"><span class="co">-}</span></a>
<a class="sourceLine" id="cb4-14" data-line-number="14"><span class="kw">module</span> <span class="dt">W</span> <span class="kw">where</span></a></code></pre></div>
<p>Here’s how it renders using 2.13.2:</p>
<figure>
<img src="/images/oldinfobox.png" alt="Old module info box" /><figcaption>Old module info box</figcaption>
</figure>
<p>and here is how it renders with 2.14.1:</p>
<figure>
<img src="/images/newinfobox.png" alt="New module info box" /><figcaption>New module info box</figcaption>
</figure>
<p>As you can see, perhaps copyright holders could be presented better. Perhaps in the next release each author will be on its own line, see ticket #279.</p></li>
<li><p>Improved Unicode support</p>
<p>Unicode support previously was very finicky. We now have a new parser which can handle unicode much better. Here’s an example comment with a single definition list:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="co">-- | [灼眼のシャナ] ℕ ℤ ℚ</span></a>
<a class="sourceLine" id="cb5-2" data-line-number="2"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb5-3" data-line-number="3">f <span class="fu">=</span> ()</a></code></pre></div>
<p>Here’s how 2.13.2 renders it:</p>
<figure>
<img src="/images/oldunicoderendering.png" alt="Old unicode rendering" /><figcaption>Old unicode rendering</figcaption>
</figure>
<p>and here’s how 2.14.1 renders it:</p>
<figure>
<img src="/images/newunicoderendering.png" alt="New unicode rendering" /><figcaption>New unicode rendering</figcaption>
</figure>
<p>Much better! Notice a character missing in the old rendering.</p></li>
<li><p>Bold markup support</p>
<p>I have covered this one in the past so here’s only a brief mention. Double underscores are used to denote that something is bald.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb6-1" data-line-number="1"><span class="co">-- | This is bold: __Hello world. Underscores_are_allowed__</span></a>
<a class="sourceLine" id="cb6-2" data-line-number="2"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb6-3" data-line-number="3">f <span class="fu">=</span> ()</a></code></pre></div>
<figure>
<img src="/images/newbold.png" alt="Bold support" /><figcaption>Bold support</figcaption>
</figure>
<p>Note that just like with other such markup (emphasis), we do not allow the user to stretch it over multiple lines.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="co">-- | This is not bold: __Hello world.</span></a>
<a class="sourceLine" id="cb7-2" data-line-number="2"><span class="co">-- Underscores_are_allowed__</span></a>
<a class="sourceLine" id="cb7-3" data-line-number="3"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb7-4" data-line-number="4">f <span class="fu">=</span> ()</a></code></pre></div>
<figure>
<img src="/images/notbold.png" alt="No multiline support" /><figcaption>No multiline support</figcaption>
</figure>
<p>This is by design. We feel that extra complexity of implementation and the fact that it changes how 2.13.2 behaved does not warrant such support. See ticket #126 for minor discussion.</p></li>
<li><p>Nested paragraphs</p>
<p>This is a pretty big addition and if you are the type of person that tries to format their comments so that they look nice in source, you’ll probably need to pay attention. Basically, we allow something like what Markdown allows: nesting things under list elements (such as more list elements and so on). A simple example would be nesting some a code snippet and another list under some other list. I’m actually showing off two features here. Consider</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="co">{-|</span></a>
<a class="sourceLine" id="cb8-2" data-line-number="2"><span class="co">* This is some list</span></a>
<a class="sourceLine" id="cb8-3" data-line-number="3"></a>
<a class="sourceLine" id="cb8-4" data-line-number="4"><span class="co">    @</span></a>
<a class="sourceLine" id="cb8-5" data-line-number="5"><span class="co">    This</span></a>
<a class="sourceLine" id="cb8-6" data-line-number="6"><span class="co">    is</span></a>
<a class="sourceLine" id="cb8-7" data-line-number="7"><span class="co">    code</span></a>
<a class="sourceLine" id="cb8-8" data-line-number="8"><span class="co">    @</span></a>
<a class="sourceLine" id="cb8-9" data-line-number="9"></a>
<a class="sourceLine" id="cb8-10" data-line-number="10"><span class="co">    * Another list</span></a>
<a class="sourceLine" id="cb8-11" data-line-number="11"><span class="co">    * Second element of inner list, not separated by line break.</span></a>
<a class="sourceLine" id="cb8-12" data-line-number="12"><span class="co">-}</span></a>
<a class="sourceLine" id="cb8-13" data-line-number="13"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb8-14" data-line-number="14">f <span class="fu">=</span> ()</a></code></pre></div>
<p>2.13.2 makes a mess out of it:</p>
<figure>
<img src="/images/oldnested.png" alt="Old nested lists" /><figcaption>Old nested lists</figcaption>
</figure>
<p>but 2.14.1 does what you might expect:</p>
<figure>
<img src="/images/newnested.png" alt="New nested lists" /><figcaption>New nested lists</figcaption>
</figure>
<p>The rule is that everything to be nested under a list element is to be indented 4 spaces from the start of the comment. Note that this is <em>not</em> 4 spaces relative from start of the previous list. You also have to make sure that the nested paragraph is separated by a line break so that Haddock doesn’t simply think it’s the continuation of the list.</p>
<p>A double nesting will therefore look like this:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="co">{-|</span></a>
<a class="sourceLine" id="cb9-2" data-line-number="2"><span class="co">* Top level</span></a>
<a class="sourceLine" id="cb9-3" data-line-number="3"></a>
<a class="sourceLine" id="cb9-4" data-line-number="4"><span class="co">    * First nested</span></a>
<a class="sourceLine" id="cb9-5" data-line-number="5"></a>
<a class="sourceLine" id="cb9-6" data-line-number="6"><span class="co">        * Second nested</span></a>
<a class="sourceLine" id="cb9-7" data-line-number="7"><span class="co">-}</span></a>
<a class="sourceLine" id="cb9-8" data-line-number="8"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb9-9" data-line-number="9">f <span class="fu">=</span> ()</a></code></pre></div>
<figure>
<img src="/images/twicenested.png" alt="Twice nested" /><figcaption>Twice nested</figcaption>
</figure>
<p>Those with sharp eyes will notice that I have two list elements not broken up by the line break in the initial example. This in now allowed as long as the list elements are of the same type:</p>
<p>This is now fine:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb10-1" data-line-number="1"><span class="co">-- |</span></a>
<a class="sourceLine" id="cb10-2" data-line-number="2"><span class="co">-- * foo</span></a>
<a class="sourceLine" id="cb10-3" data-line-number="3"><span class="co">-- * bar</span></a></code></pre></div>
<p>but this is <em>not</em> fine:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="co">-- |</span></a>
<a class="sourceLine" id="cb11-2" data-line-number="2"><span class="co">-- * foo</span></a>
<a class="sourceLine" id="cb11-3" data-line-number="3"><span class="co">-- 1. bar</span></a></code></pre></div>
<p>Haddock will think it’s just a single list element and it will look something like this:</p>
<figure>
<img src="/images/differentbreak.png" alt="Different type no break" /><figcaption>Different type no break</figcaption>
</figure>
<p>Please refer to <a href="http://www.haskell.org/haddock/doc/html/ch03s08.html#idp1371090476">list section of the docs</a> for details. These changes mean that you can write much nicer docs but they also mean that if you wrote something that wasn’t exactly model Haddock before, it might now look radically different! I know that even GHC is guilty of this.</p></li>
<li><p>Better escaping</p>
<p>We now have much better escaping behaviour. Consider</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb12-1" data-line-number="1"><span class="co">-- | &lt; http:/haskell.org Haskell.org loves \&gt;\&gt;= &gt;</span></a></code></pre></div>
<p>2.13.2 messes up:</p>
<figure>
<img src="/images/oldlinkescape.png" alt="Old link escape" /><figcaption>Old link escape</figcaption>
</figure>
<p>But 2.14.1 works as we’d like it to:</p>
<figure>
<img src="/images/newlinkescape.png" alt="New link escape" /><figcaption>New link escape</figcaption>
</figure>
<p>It is actually impossible to have the <code>&gt;</code> character in the link or alt text even with HTML escapes because we don’t accept markup there so it won’t get converted.</p>
<p>If you don’t need the alt text, we now even automatically try to convert text to links. Consider</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb13-1" data-line-number="1"><span class="co">-- | http://haskell.org is cool</span></a>
<a class="sourceLine" id="cb13-2" data-line-number="2"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb13-3" data-line-number="3">f <span class="fu">=</span> ()</a></code></pre></div>
<p>2.13.2 doesn’t do what we want at all and even swallows up the forward slashes because it thinks it sees (empty) emphasis:</p>
<figure>
<img src="/images/oldautolink.png" alt="Old autolink" /><figcaption>Old autolink</figcaption>
</figure>
<p>2.14.1 does something much more reasonable:</p>
<figure>
<img src="/images/newautolink.png" alt="New autolink" /><figcaption>New autolink</figcaption>
</figure>
<p>You should notice that escaping things is much more reasonable now.</p></li>
<li><p>Header markup</p>
<p>Headers in regular comments (rather than just for sections) are now allowed. The syntax is multiple <code>=</code> characters, from 0 up to 6. Each back-end decides how to render the different header levels itself.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb14-1" data-line-number="1"><span class="co">{-|</span></a>
<a class="sourceLine" id="cb14-2" data-line-number="2"><span class="co">= Top level</span></a>
<a class="sourceLine" id="cb14-3" data-line-number="3"><span class="co">* Hello</span></a>
<a class="sourceLine" id="cb14-4" data-line-number="4"><span class="co">* World</span></a>
<a class="sourceLine" id="cb14-5" data-line-number="5"></a>
<a class="sourceLine" id="cb14-6" data-line-number="6"><span class="co">== Subheader</span></a>
<a class="sourceLine" id="cb14-7" data-line-number="7"><span class="co">=== Subsubheader</span></a>
<a class="sourceLine" id="cb14-8" data-line-number="8"><span class="co">@More stuff!@</span></a>
<a class="sourceLine" id="cb14-9" data-line-number="9"><span class="co">-}</span></a>
<a class="sourceLine" id="cb14-10" data-line-number="10"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb14-11" data-line-number="11">f <span class="fu">=</span> ()</a></code></pre></div>
<figure>
<img src="/images/headers.png" alt="Headers" /><figcaption>Headers</figcaption>
</figure>
<p>Note that headers have to be at the beginning of a paragraph but we do allow a paragraph to follow without a line break right after it. This allows you to write down things like lists and another header straight after.</p></li>
<li><p>Parser should no longer fail to parse any markup</p>
<p>We now aim to be able to parse everything. This means that you should never see a parse failure caused by bad Haddock syntax. For example</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb15-1" data-line-number="1"><span class="co">-- | [ hello</span></a>
<a class="sourceLine" id="cb15-2" data-line-number="2"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb15-3" data-line-number="3">f <span class="fu">=</span> ()</a></code></pre></div>
<p>fails on 2.13.2 with a parse error: <code>doc comment parse failed:  [ hello</code>. This will render as you’d expect on 2.14.1:</p>
<figure>
<img src="/images/noerror.png" alt="No parse error" /><figcaption>No parse error</figcaption>
</figure>
<p>This means that if you had a documentation that failed to parse due to such error before, it will now (silently) succeed.</p>
<p><strong>Important</strong>: please note that you can still have a different kind of parse error. If your comment is at a place where we don’t expect it, that’s an error. For example, the following will throw a parse error:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb16-1" data-line-number="1"><span class="kw">data</span> <span class="dt">F</span> <span class="fu">=</span> <span class="dt">F</span> () <span class="co">-- ^ Doc for first ()</span></a>
<a class="sourceLine" id="cb16-2" data-line-number="2">           () <span class="co">-- ^ Doc for second ()</span></a></code></pre></div>
<p>gives us <code>W.hs:18:12: parse error on input ‘(’</code> because we don’t support documentation of each parameter to the constructors.</p>
<p>Please do not report these as bugs! If you do get a <code>doc comment   parse failed</code> then report that, you should not be seeing any of these anymore.</p></li>
<li><p>{-# OPTIONS_HADDOCK show-extensions #-} pragma will show the GHC extensions enabled in the module.</p>
<p>I think this is a pretty nifty one. Consider</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb17-1" data-line-number="1"><span class="ot">{-# LANGUAGE UnicodeSyntax #-}</span></a>
<a class="sourceLine" id="cb17-2" data-line-number="2"><span class="ot">{-# LANGUAGE TypeFamilies #-}</span></a>
<a class="sourceLine" id="cb17-3" data-line-number="3"><span class="ot">{-# LANGUAGE FunctionalDependencies #-}</span></a>
<a class="sourceLine" id="cb17-4" data-line-number="4"><span class="ot">{-# LANGUAGE DataKinds #-}</span></a>
<a class="sourceLine" id="cb17-5" data-line-number="5"><span class="ot">{-# LANGUAGE TypeOperators #-}</span></a>
<a class="sourceLine" id="cb17-6" data-line-number="6"><span class="ot">{-# LANGUAGE FlexibleInstances #-}</span></a>
<a class="sourceLine" id="cb17-7" data-line-number="7"><span class="ot">{-# OPTIONS_HADDOCK show-extensions #-}</span></a>
<a class="sourceLine" id="cb17-8" data-line-number="8"><span class="kw">module</span> <span class="dt">W</span> <span class="kw">where</span></a></code></pre></div>
<p>You can now ask Haddock to list <strong>all</strong> enabled extensions (even those implicit ones) with the Haddock pragma that I show above. This particular example renders like this:</p>
<figure>
<img src="/images/extpragma.png" alt="Ext pragma" /><figcaption>Ext pragma</figcaption>
</figure>
<p>If you have a Haskell98/2010/whatever pragma too, that will also get shown. Any extension implied by the current language (H98,2010) is not shown.</p>
<p>I decided to show all the extensions, including the ones pulled in by stronger ones to discourage enabling the most powerful extensions without a good reason.</p>
<p>This option is not a default. Do you think it should be?</p></li>
<li><p>Properly render License field (#271)</p>
<p>There was a bug where we rendered the wrong thing in the License field. I can’t show you because it already has been patched up. I simply mention this for completeness.</p></li>
<li><p>Print type/data family instances (for exported types only)</p>
<p>Fairly self explanatory, your type/data family instances now get shown in the documentation.</p>
<p>This example is a pretty big one because there’s a fair amount of stuff going into it. This is actually a stripped down version used by Haddock for testing.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb18-1" data-line-number="1"><span class="ot">{-# LANGUAGE TypeFamilies, UndecidableInstances, PolyKinds, TypeOperators,</span></a>
<a class="sourceLine" id="cb18-2" data-line-number="2"><span class="ot">             DataKinds, MultiParamTypeClasses, GADTs #-}</span></a>
<a class="sourceLine" id="cb18-3" data-line-number="3"><span class="kw">module</span> <span class="dt">W</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb18-4" data-line-number="4"></a>
<a class="sourceLine" id="cb18-5" data-line-number="5"><span class="co">-- | Doc for: data X</span></a>
<a class="sourceLine" id="cb18-6" data-line-number="6"><span class="kw">data</span> <span class="dt">X</span></a>
<a class="sourceLine" id="cb18-7" data-line-number="7">  <span class="fu">=</span> <span class="dt">X</span>   <span class="co">-- ^ Doc for: X</span></a>
<a class="sourceLine" id="cb18-8" data-line-number="8">  <span class="fu">|</span> <span class="dt">XX</span>  <span class="co">-- ^ Doc for: XX</span></a>
<a class="sourceLine" id="cb18-9" data-line-number="9">  <span class="fu">|</span> <span class="dt">XXX</span> <span class="co">-- ^ Doc for: XXX</span></a>
<a class="sourceLine" id="cb18-10" data-line-number="10"></a>
<a class="sourceLine" id="cb18-11" data-line-number="11"><span class="co">-- | Doc for: data Y</span></a>
<a class="sourceLine" id="cb18-12" data-line-number="12"><span class="kw">data</span> <span class="dt">Y</span></a>
<a class="sourceLine" id="cb18-13" data-line-number="13"></a>
<a class="sourceLine" id="cb18-14" data-line-number="14"><span class="co">-- | Doc for: class Test a</span></a>
<a class="sourceLine" id="cb18-15" data-line-number="15"><span class="kw">class</span> <span class="dt">Test</span> a</a>
<a class="sourceLine" id="cb18-16" data-line-number="16"></a>
<a class="sourceLine" id="cb18-17" data-line-number="17"><span class="co">-- | Doc for: instance Test X</span></a>
<a class="sourceLine" id="cb18-18" data-line-number="18"><span class="kw">instance</span> <span class="dt">Test</span> <span class="dt">X</span></a>
<a class="sourceLine" id="cb18-19" data-line-number="19"><span class="co">-- | Doc for: instance Test Y</span></a>
<a class="sourceLine" id="cb18-20" data-line-number="20"><span class="kw">instance</span> <span class="dt">Test</span> <span class="dt">Y</span></a>
<a class="sourceLine" id="cb18-21" data-line-number="21"></a>
<a class="sourceLine" id="cb18-22" data-line-number="22"><span class="co">-- | Doc for: type family Foo a</span></a>
<a class="sourceLine" id="cb18-23" data-line-number="23"><span class="kw">type</span> family <span class="dt">Foo</span><span class="ot"> a ::</span> k</a>
<a class="sourceLine" id="cb18-24" data-line-number="24"></a>
<a class="sourceLine" id="cb18-25" data-line-number="25"><span class="co">-- | Doc for: type instance Foo X = Y</span></a>
<a class="sourceLine" id="cb18-26" data-line-number="26"><span class="kw">type</span> <span class="kw">instance</span> <span class="dt">Foo</span> <span class="dt">X</span> <span class="fu">=</span> <span class="dt">Y</span></a>
<a class="sourceLine" id="cb18-27" data-line-number="27"><span class="co">-- | Doc for: type instance Foo Y = X</span></a>
<a class="sourceLine" id="cb18-28" data-line-number="28"><span class="kw">type</span> <span class="kw">instance</span> <span class="dt">Foo</span> <span class="dt">Y</span> <span class="fu">=</span> <span class="dt">X</span></a>
<a class="sourceLine" id="cb18-29" data-line-number="29"></a>
<a class="sourceLine" id="cb18-30" data-line-number="30"><span class="co">-- | Doc for: class Assoc a</span></a>
<a class="sourceLine" id="cb18-31" data-line-number="31"><span class="kw">class</span> <span class="dt">Assoc</span> a <span class="kw">where</span></a>
<a class="sourceLine" id="cb18-32" data-line-number="32">  <span class="co">-- | Doc for: data AssocD a</span></a>
<a class="sourceLine" id="cb18-33" data-line-number="33">  <span class="kw">data</span> <span class="dt">AssocD</span><span class="ot"> a ::</span> <span class="fu">*</span></a>
<a class="sourceLine" id="cb18-34" data-line-number="34">  <span class="co">-- | Doc for: type AssocT a</span></a>
<a class="sourceLine" id="cb18-35" data-line-number="35">  <span class="kw">type</span> <span class="dt">AssocT</span><span class="ot"> a ::</span> <span class="fu">*</span></a>
<a class="sourceLine" id="cb18-36" data-line-number="36"></a>
<a class="sourceLine" id="cb18-37" data-line-number="37"><span class="co">-- | Doc for: instance Assoc X</span></a>
<a class="sourceLine" id="cb18-38" data-line-number="38"><span class="kw">instance</span> <span class="dt">Assoc</span> <span class="dt">X</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb18-39" data-line-number="39">  <span class="co">-- | Doc for: data AssocD X = AssocX</span></a>
<a class="sourceLine" id="cb18-40" data-line-number="40">  <span class="kw">data</span> <span class="dt">AssocD</span> <span class="dt">X</span> <span class="fu">=</span> <span class="dt">AssocX</span> <span class="co">-- ^ Doc for: AssocX</span></a>
<a class="sourceLine" id="cb18-41" data-line-number="41">  <span class="co">-- | Doc for: type AssocT X = Foo X</span></a>
<a class="sourceLine" id="cb18-42" data-line-number="42">  <span class="kw">type</span> <span class="dt">AssocT</span> <span class="dt">X</span> <span class="fu">=</span> <span class="dt">Foo</span> <span class="dt">X</span></a>
<a class="sourceLine" id="cb18-43" data-line-number="43"></a>
<a class="sourceLine" id="cb18-44" data-line-number="44"><span class="co">-- | Doc for: instance Assoc Y</span></a>
<a class="sourceLine" id="cb18-45" data-line-number="45"><span class="kw">instance</span> <span class="dt">Assoc</span> <span class="dt">Y</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb18-46" data-line-number="46">  <span class="co">-- | Doc for: data AssocD Y = AssocY</span></a>
<a class="sourceLine" id="cb18-47" data-line-number="47">  <span class="kw">data</span> <span class="dt">AssocD</span> <span class="dt">Y</span> <span class="fu">=</span> <span class="dt">AssocY</span> <span class="co">-- ^ Doc for: AssocY</span></a></code></pre></div>
<p>and here’s part of how it looks</p>
<figure>
<img src="/images/typefams.png" alt="Type families" /><figcaption>Type families</figcaption>
</figure></li>
<li><p>Fix display of poly-kinded type operators (#189)</p>
<figure>
<img src="/images/oldpoly.png" alt="Old poly-kinded rendering" /><figcaption>Old poly-kinded rendering</figcaption>
</figure>
<figure>
<img src="/images/newpoly.png" alt="New poly-kinded rendering" /><figcaption>New poly-kinded rendering</figcaption>
</figure>
<p>We’re still unsure how to display this to the user but at least now it’s not completely wrong. Suggestions are most welcome, please comment on #189.</p></li>
<li><p>PatternSynonyms support</p>
<p>GHC 7.8 now has support for <a href="https://ghc.haskell.org/trac/ghc/wiki/PatternSynonyms">pattern synonyms</a>. Here’s an example right from Haddock test-suite.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb19-1" data-line-number="1"><span class="ot">{-# LANGUAGE PatternSynonyms, PolyKinds, TypeOperators #-}</span></a>
<a class="sourceLine" id="cb19-2" data-line-number="2"></a>
<a class="sourceLine" id="cb19-3" data-line-number="3"><span class="co">-- | Testing some pattern synonyms</span></a>
<a class="sourceLine" id="cb19-4" data-line-number="4"><span class="kw">module</span> <span class="dt">W</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb19-5" data-line-number="5"><span class="co">-- | FooType doc</span></a>
<a class="sourceLine" id="cb19-6" data-line-number="6"><span class="kw">data</span> <span class="dt">FooType</span> x <span class="fu">=</span> <span class="dt">FooCtor</span> x</a>
<a class="sourceLine" id="cb19-7" data-line-number="7"></a>
<a class="sourceLine" id="cb19-8" data-line-number="8"><span class="co">-- | Pattern synonym for &#39;Foo&#39; x</span></a>
<a class="sourceLine" id="cb19-9" data-line-number="9">pattern <span class="dt">Foo</span> x <span class="fu">=</span> <span class="dt">FooCtor</span> x</a>
<a class="sourceLine" id="cb19-10" data-line-number="10"></a>
<a class="sourceLine" id="cb19-11" data-line-number="11"><span class="co">-- | Pattern synonym for &#39;Bar&#39; x</span></a>
<a class="sourceLine" id="cb19-12" data-line-number="12">pattern <span class="dt">Bar</span> x <span class="fu">=</span> <span class="dt">FooCtor</span> (<span class="dt">Foo</span> x)</a>
<a class="sourceLine" id="cb19-13" data-line-number="13"></a>
<a class="sourceLine" id="cb19-14" data-line-number="14"><span class="co">-- | Pattern synonym for (&#39;:&lt;-&gt;&#39;)</span></a>
<a class="sourceLine" id="cb19-15" data-line-number="15">pattern x <span class="fu">:&lt;-&gt;</span> y <span class="fu">=</span> (<span class="dt">Foo</span> x, <span class="dt">Bar</span> y)</a>
<a class="sourceLine" id="cb19-16" data-line-number="16"></a>
<a class="sourceLine" id="cb19-17" data-line-number="17"><span class="co">-- | Doc for (&#39;&gt;&lt;&#39;)</span></a>
<a class="sourceLine" id="cb19-18" data-line-number="18"><span class="kw">data</span> (<span class="ot">a ::</span> <span class="fu">*</span>) <span class="fu">&gt;&lt;</span> b <span class="fu">=</span> <span class="dt">Empty</span></a>
<a class="sourceLine" id="cb19-19" data-line-number="19"></a>
<a class="sourceLine" id="cb19-20" data-line-number="20"><span class="co">-- | Pattern for &#39;Empty&#39;</span></a>
<a class="sourceLine" id="cb19-21" data-line-number="21">pattern <span class="dt">E</span> <span class="fu">=</span> <span class="dt">Empty</span></a></code></pre></div>
<p>The rendering is still pretty experimental so suggestion welcome!</p>
<figure>
<img src="/images/patsyn.png" alt="Pattern Synonyms" /><figcaption>Pattern Synonyms</figcaption>
</figure></li>
<li><p>Fix display of implicit parameters (#260)</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb20-1" data-line-number="1"><span class="ot">{-# LANGUAGE RankNTypes #-}</span></a>
<a class="sourceLine" id="cb20-2" data-line-number="2"><span class="ot">{-# LANGUAGE ImplicitParams #-}</span></a>
<a class="sourceLine" id="cb20-3" data-line-number="3"><span class="kw">module</span> <span class="dt">W</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb20-4" data-line-number="4"></a>
<a class="sourceLine" id="cb20-5" data-line-number="5"><span class="kw">data</span> <span class="dt">Configuration</span></a>
<a class="sourceLine" id="cb20-6" data-line-number="6"></a>
<a class="sourceLine" id="cb20-7" data-line-number="7"><span class="ot">c ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> ((<span class="fu">?</span><span class="ot">configuration ::</span> <span class="dt">Configuration</span>) <span class="ot">=&gt;</span> <span class="dt">IO</span> b) <span class="ot">-&gt;</span> <span class="dt">IO</span> b</a>
<a class="sourceLine" id="cb20-8" data-line-number="8">c <span class="fu">=</span> undefined</a></code></pre></div>
<figure>
<img src="/images/oldimp.png" alt="Broken implicit params rendering" /><figcaption>Broken implicit params rendering</figcaption>
</figure>
<figure>
<img src="/images/newimp.png" alt="Fixed implicit params rendering" /><figcaption>Fixed implicit params rendering</figcaption>
</figure></li>
<li><p>Fix rendering of Contents when links are present (#276)</p>
<p>Given</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb21-1" data-line-number="1"><span class="kw">module</span> <span class="dt">W</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb21-2" data-line-number="2"></a>
<a class="sourceLine" id="cb21-3" data-line-number="3"><span class="co">-- * Section header with &#39;f&#39; link</span></a>
<a class="sourceLine" id="cb21-4" data-line-number="4"></a>
<a class="sourceLine" id="cb21-5" data-line-number="5"><span class="co">-- | f doc</span></a>
<a class="sourceLine" id="cb21-6" data-line-number="6"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb21-7" data-line-number="7">f <span class="fu">=</span> ()</a></code></pre></div>
<p>We used to have a problem where a link in the header would break the Contents box rendering.</p>
<figure>
<img src="/images/oldcont.png" alt="Old contents" /><figcaption>Old contents</figcaption>
</figure>
<p>That is now fixed. Note that you can no longer click on ‘f’ in the Contents box to be taken there. I feel that it’s the expected way.</p>
<figure>
<img src="/images/newcont.png" alt="New contents" /><figcaption>New contents</figcaption>
</figure></li>
<li><p>Fix documentation duplication on record fields (#195)</p>
<p>I think this is going to be a pretty controversial one. Consider</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb22-1" data-line-number="1"><span class="kw">module</span> <span class="dt">W</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb22-2" data-line-number="2"></a>
<a class="sourceLine" id="cb22-3" data-line-number="3"><span class="kw">data</span> <span class="dt">F</span> <span class="fu">=</span> <span class="dt">FOne</span> {<span class="ot"> field ::</span> () <span class="co">-- ^ Doc for FOne field</span></a>
<a class="sourceLine" id="cb22-4" data-line-number="4">              }</a>
<a class="sourceLine" id="cb22-5" data-line-number="5">       <span class="fu">|</span> <span class="dt">FTwo</span> {<span class="ot"> field ::</span> () <span class="co">-- ^ Doc for FTwo field</span></a>
<a class="sourceLine" id="cb22-6" data-line-number="6">              }</a></code></pre></div>
<p>As ‘field’ is actually the same function, in the past Haddock would join the comments (it’s in the weird order due to an unfixed bug):</p>
<figure>
<img src="/images/oldrecord.png" alt="Old record doc rendering" /><figcaption>Old record doc rendering</figcaption>
</figure>
<p>We now instead take the doc of the first field to occur. Note that is used even if the first field has no comment and others do.</p>
<figure>
<img src="/images/newrecord.png" alt="New record doc rendering" /><figcaption>New record doc rendering</figcaption>
</figure>
<p>See ticket #195 if you want to discuss this change. Both behaviours are weird but I think no one intentionally used the old behaviour.</p></li>
<li><p>Add <code>--source-entity-line</code> for exact line links (eg. things defined inside TH splices) (#79)</p>
<p>This allows HsColour to insert anchors for TH declarations. Nothing to show here, check the ticket for details.</p></li>
<li><p>Display fixity information for names with nonstandard fixities</p>
<p>There’s no a mechanism in place to display fixity of (type) operators and infix functions. Includes exotic things like type families and pattern synonyms. Code omitted but there’s nothing special you have to do, your new docs should automagically have fixities shown.</p>
<figure>
<img src="/images/fixities.png" alt="Fixity rendering" /><figcaption>Fixity rendering</figcaption>
</figure></li>
<li><p>Bird tracks specified like “&gt; code” no longer suffer from an extra leading space in the code output</p>
<p>Pretty self explanatory. We strip a leading space from code blocks generated by bird tracks.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb23-1" data-line-number="1"><span class="co">-- |</span></a>
<a class="sourceLine" id="cb23-2" data-line-number="2"><span class="co">-- &gt; hello</span></a>
<a class="sourceLine" id="cb23-3" data-line-number="3"><span class="co">-- &gt; world</span></a>
<a class="sourceLine" id="cb23-4" data-line-number="4"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb23-5" data-line-number="5">f <span class="fu">=</span> ()</a></code></pre></div>
<figure>
<img src="/images/oldbird.png" alt="Old bird tracks" /><figcaption>Old bird tracks</figcaption>
</figure>
<figure>
<img src="/images/newbird.png" alt="New bird tracks" /><figcaption>New bird tracks</figcaption>
</figure>
<p>This is also planned for the ‘@’ style code blocks which should have this implemented in the next Haddock release, most likely 2.15.0 coming out with GHC 7.8.2.</p></li>
<li><p>Render * and -&gt; with their UnicodeSyntax equivalents if -U is enabled</p>
<p>Replaces * and -&gt; in extra places compared to 2.13.2.</p>
<figure>
<img src="/images/oldunicode.png" alt="Old unicode syntax" /><figcaption>Old unicode syntax</figcaption>
</figure>
<figure>
<img src="/images/newunicode.png" alt="New unicode syntax" /><figcaption>New unicode syntax</figcaption>
</figure></li>
<li><p>Display minimal complete definitions for type classes</p>
<p>I feel this is a nice feature. <a href="https://ghc.haskell.org/trac/ghc/ticket/7633">GHC now supports MINIMAL pragmas</a> and we are now able to display it in the docs. Another example right out of the Haddock test-suite:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb24-1" data-line-number="1"><span class="kw">module</span> <span class="dt">W</span></a>
<a class="sourceLine" id="cb24-2" data-line-number="2">  ( <span class="dt">Foo</span>(<span class="fu">..</span>)</a>
<a class="sourceLine" id="cb24-3" data-line-number="3">  , <span class="dt">Weird</span>(<span class="fu">..</span>)</a>
<a class="sourceLine" id="cb24-4" data-line-number="4">  , <span class="dt">NoMins</span>(<span class="fu">..</span>)</a>
<a class="sourceLine" id="cb24-5" data-line-number="5">  , <span class="dt">FullMin</span>(<span class="fu">..</span>)</a>
<a class="sourceLine" id="cb24-6" data-line-number="6">  , <span class="dt">PartialMin</span>(ccc)</a>
<a class="sourceLine" id="cb24-7" data-line-number="7">  , <span class="dt">EmptyMin</span>(<span class="fu">..</span>)</a>
<a class="sourceLine" id="cb24-8" data-line-number="8">  ) <span class="kw">where</span></a>
<a class="sourceLine" id="cb24-9" data-line-number="9"></a>
<a class="sourceLine" id="cb24-10" data-line-number="10"><span class="kw">class</span> <span class="dt">Foo</span> a <span class="kw">where</span></a>
<a class="sourceLine" id="cb24-11" data-line-number="11">  <span class="co">-- | Any two of these are required...</span></a>
<a class="sourceLine" id="cb24-12" data-line-number="12">  foo, bar,<span class="ot"> bat ::</span> a</a>
<a class="sourceLine" id="cb24-13" data-line-number="13"></a>
<a class="sourceLine" id="cb24-14" data-line-number="14">  <span class="co">-- | .. or just this</span></a>
<a class="sourceLine" id="cb24-15" data-line-number="15"><span class="ot">  fooBarBat ::</span> (a,a,a)</a>
<a class="sourceLine" id="cb24-16" data-line-number="16"></a>
<a class="sourceLine" id="cb24-17" data-line-number="17">  <span class="ot">{-# MINIMAL (foo, bar) | (bar, bat) | (foo, bat) | fooBarBat #-}</span></a>
<a class="sourceLine" id="cb24-18" data-line-number="18"></a>
<a class="sourceLine" id="cb24-19" data-line-number="19"><span class="kw">class</span> <span class="dt">Weird</span> a <span class="kw">where</span></a>
<a class="sourceLine" id="cb24-20" data-line-number="20">  a,b,c,d,e,f,<span class="ot">g ::</span> a</a>
<a class="sourceLine" id="cb24-21" data-line-number="21"></a>
<a class="sourceLine" id="cb24-22" data-line-number="22">  <span class="ot">{-# MINIMAL ((a, b), c | (d | (e, (f | g)))) #-}</span></a>
<a class="sourceLine" id="cb24-23" data-line-number="23"></a>
<a class="sourceLine" id="cb24-24" data-line-number="24"><span class="kw">class</span> <span class="dt">NoMins</span> a <span class="kw">where</span></a>
<a class="sourceLine" id="cb24-25" data-line-number="25">  x,y,<span class="ot">z ::</span> a</a>
<a class="sourceLine" id="cb24-26" data-line-number="26"></a>
<a class="sourceLine" id="cb24-27" data-line-number="27">  <span class="co">-- | Has a default implementation!</span></a>
<a class="sourceLine" id="cb24-28" data-line-number="28">  z <span class="fu">=</span> x</a>
<a class="sourceLine" id="cb24-29" data-line-number="29"></a>
<a class="sourceLine" id="cb24-30" data-line-number="30"><span class="kw">class</span> <span class="dt">FullMin</span> a <span class="kw">where</span></a>
<a class="sourceLine" id="cb24-31" data-line-number="31">  aaa,<span class="ot">bbb ::</span> a</a>
<a class="sourceLine" id="cb24-32" data-line-number="32"></a>
<a class="sourceLine" id="cb24-33" data-line-number="33"><span class="kw">class</span> <span class="dt">PartialMin</span> a <span class="kw">where</span></a>
<a class="sourceLine" id="cb24-34" data-line-number="34">  ccc,<span class="ot">ddd ::</span> a</a>
<a class="sourceLine" id="cb24-35" data-line-number="35"></a>
<a class="sourceLine" id="cb24-36" data-line-number="36"><span class="kw">class</span> <span class="dt">EmptyMin</span> a <span class="kw">where</span></a>
<a class="sourceLine" id="cb24-37" data-line-number="37">  eee,<span class="ot">fff ::</span> a</a>
<a class="sourceLine" id="cb24-38" data-line-number="38">  eee <span class="fu">=</span> fff</a>
<a class="sourceLine" id="cb24-39" data-line-number="39">  fff <span class="fu">=</span> undefined</a></code></pre></div>
<figure>
<img src="/images/miniprag.png" alt="Minimal pragma" /><figcaption>Minimal pragma</figcaption>
</figure>
<p>Again I ask you to ignore the silly ordering of some grouped functions, this is the aforementioned old bug. Hopefully we can fix it by the next release.</p></li>
<li><p>Hide right hand side of TF instances with hidden names on the RHS</p>
<p>Changes a bit which TF RHSs are hidden. It is a change between 2.14.0 and 2.14.1 and is only mentioned for completeness.</p></li>
</ul>
<p>This is it for all the changes I can think of but I’m sure I missed something! There was some other minor stuff fixed up that doesn’t deserve a mention on its own (such as fixing bullet point rendering in constructor docs, #281) so I encourage you to read the commit history if you need to know all the little details.</p>
<p>While I’d love to end it here, I do have to admit that there’s a regression in this release which we don’t get to fix until GHC 7.8.2.</p>
<p>Namely, if you have a (very common) comment like this:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb25-1" data-line-number="1"><span class="co">-- |</span></a>
<a class="sourceLine" id="cb25-2" data-line-number="2"><span class="co">-- @</span></a>
<a class="sourceLine" id="cb25-3" data-line-number="3"><span class="co">-- some code</span></a>
<a class="sourceLine" id="cb25-4" data-line-number="4"><span class="co">-- goes here</span></a>
<a class="sourceLine" id="cb25-5" data-line-number="5"><span class="co">-- @</span></a>
<a class="sourceLine" id="cb25-6" data-line-number="6"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb25-7" data-line-number="7">f <span class="fu">=</span> ()</a></code></pre></div>
<p>2.13.2 will render it like this:</p>
<figure>
<img src="/images/oldblock.png" alt="Old codeblock rendering" /><figcaption>Old codeblock rendering</figcaption>
</figure>
<p>and 2.14.1 like this:</p>
<figure>
<img src="/images/newblock.png" alt="New codeblock rendering" /><figcaption>New codeblock rendering</figcaption>
</figure>
<p>The problem is that while Haskellers are used to putting a space after the comment marker <code>--</code>, that space is actually a part of a comment and we end up with an extra ‘empty’ line which actually has a single space in front of it. This is the line with the closing @ on it.</p>
<p>All of the following let you workaround the problem:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb26-1" data-line-number="1"><span class="co">-- |</span></a>
<a class="sourceLine" id="cb26-2" data-line-number="2"><span class="co">-- &gt; some code</span></a>
<a class="sourceLine" id="cb26-3" data-line-number="3"><span class="co">-- &gt; goes here</span></a>
<a class="sourceLine" id="cb26-4" data-line-number="4"><span class="ot">f ::</span> ()</a>
<a class="sourceLine" id="cb26-5" data-line-number="5">f <span class="fu">=</span> ()</a>
<a class="sourceLine" id="cb26-6" data-line-number="6"></a>
<a class="sourceLine" id="cb26-7" data-line-number="7"><span class="co">-- |</span></a>
<a class="sourceLine" id="cb26-8" data-line-number="8"><span class="fu">--@</span></a>
<a class="sourceLine" id="cb26-9" data-line-number="9"><span class="co">--some code</span></a>
<a class="sourceLine" id="cb26-10" data-line-number="10"><span class="co">--goes here</span></a>
<a class="sourceLine" id="cb26-11" data-line-number="11"><span class="fu">--@</span></a>
<a class="sourceLine" id="cb26-12" data-line-number="12"><span class="ot">g ::</span> ()</a>
<a class="sourceLine" id="cb26-13" data-line-number="13">g <span class="fu">=</span> ()</a>
<a class="sourceLine" id="cb26-14" data-line-number="14"></a>
<a class="sourceLine" id="cb26-15" data-line-number="15"><span class="co">{-|</span></a>
<a class="sourceLine" id="cb26-16" data-line-number="16"><span class="co">@</span></a>
<a class="sourceLine" id="cb26-17" data-line-number="17"><span class="co">some code</span></a>
<a class="sourceLine" id="cb26-18" data-line-number="18"><span class="co">goes here</span></a>
<a class="sourceLine" id="cb26-19" data-line-number="19"><span class="co">@</span></a>
<a class="sourceLine" id="cb26-20" data-line-number="20"><span class="co">-}</span></a>
<a class="sourceLine" id="cb26-21" data-line-number="21"><span class="ot">i ::</span> ()</a>
<a class="sourceLine" id="cb26-22" data-line-number="22">i <span class="fu">=</span> ()</a></code></pre></div>
<p>Surprisingly, that second form is allowed. If you care a lot about the extra line, please use a workaround for now and I’m sorry! If you don’t care that it looks a bit on the ugly side for a while, we’ll have a fix in the next release, most likely to ship with GHC 7.8.2.</p>
<p>Thanks!</p>
]]></summary>
</entry>
<entry>
    <title>GSoC 2014 submission</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2014-03-18-GSoC-2014-submission.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2014-03-18-GSoC-2014-submission.html</id>
    <published>2014-03-18T17:38:28Z</published>
    <updated>2014-03-18T17:38:28Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on March 18, 2014
    
        by Fūzetsu
    
</div>

<p>Again we have come to the time where Google Summer of Code rolls around. While I have already written up, posted up for public viewing and submitted my proposal for this year, I have totally forgotten to post it here for those of you who might not follow the mailing lists!</p>
<p>Firstly I’d like to remind you that the proposal deadline is March 21st, 19:00 UTC so if you still haven’t come up with anything and would like to participate, you should start to hurry. Come to #haskell-gsoc on Freenode if you’re looking for help or feedback.</p>
<p>Secondly, I’d like to hint at possibly a second proposal which would enable you to view documentation inside GHCi and could speed up Haddock dramatically. This is still in ‘just an idea’ stage and involves storing the documentation strings in the .hi files. Check ghc-devs mailing list if you’re interested in it, have comments, or perhaps want to be the one to do this as a project!</p>
<p>Having said all that, below is my proposal in full as I submitted it not that long ago. You can check haskell-cafe for a thread with discussion about this proposal.</p>
<h2 id="yi-concurrency-usability-and-hackability">Yi concurrency, usability and hackability</h2>
<ul>
<li><p>What is the goal of the project you propose to do?</p>
<p>There are two main goals of the project: the first is to implement concurrency in the Yi text editor. The second aim is to start bringing Yi into the territory of usable and hackable editors.</p></li>
<li><p>In what ways will this project benefit the wider Haskell community?</p>
<p>While the project itself isn’t one of the core ones (such as GHC, Haddock and Cabal), I feel that there are a couple of benefits to the community:</p>
<ol type="1">
<li><p>Haskellers come closer to escaping the ELisp/vimscript hell. We can get a nicer programming environment, made and extensible in the language of our choice and get to use all the libraries that we’re used to while we’re at it.</p></li>
<li><p>We’ll have more Real World™ Haskell applications. On a more serious note, it can serve as a good example of how to do certain things with Haskell: off the top of my head, it demonstrates the use of dyre and gtk2hs in a real-world scenario rather than a 5 line example on the Haskell wiki. If the project is successful, we can add concurrency to this.</p></li>
<li><p>Work on Yi (now and in the future) will undoubtedly spawn new Haskell libraries usable in other projects. My personal experience with Yi shows that it’s actually very comfortable to write a generic library which does what we need and then having a separate package which uses the library to actually interact with Yi.</p></li>
</ol>
<p>Other than the Haskell community in general, this project should benefit anyone with some interest in text editors. I think it’s safe to say that happens to be a large majority of Haskellers: most of us want nicer integration with Haskell tools and libraries[citation needed] and now it’ll be possible through direct, type-checked library access.</p></li>
<li><p>Can you give some more detailed design of what precisely you intend to achieve?</p>
<p>The concurrency goal will involve careful study of Yi’s inner workings in order to try and accommodate concurrency. It might come as a surprise to many but currently Yi has no such support. There are various ways to do concurrency and the first part of the project will concentrate on settling for one. An example of two different ways is to extend the existing Yi engine with classical tools (MVars, channels) to accommodate for concurrency that way. An alternative way would be to modify the engine so that concurrency support is natural. Such experiment was started <a href="https://github.com/ethercrow/y">here</a> using the sodium FRP package which would give us concurrency ‘for free’. The experiment is not complete and this is the kind of thing that will first be explored.</p>
<p>Of course once we settle for a method, time will be spent implementing it. In the end, this should allow us to do things such as fire Yi events periodically or do network transfers without having to halt the whole editor. Editors such as emacs which are single-threaded effectively hop back-and-forth between tasks on a single thread. We aim to provide the ability to simply have tasks on different threads which allows us to take advantage of system resources much better.</p>
<p>The second part of the project is to make Yi more usable and hackable. Usability here involves fixing bugs apparent to the user and hackability involves bugs apparent to developers. Further, as part of usability, I plan to implement as many editor modes as I find time for.</p>
<p>Specifically, here are some open bugs that I hope to either fix or to make a considerate progress on: #445, #397, #517, #519, #515, #516, #513 (concurrency), #512, #507, #504, #502, #501, #499, #497, #493, #487, #478, #477, #468, #465, #399, #396, #391, #390, #382, #322, #295, #172, #160, #106, #145, #112, #82, #509.</p>
<p>All the bug numbers can be viewed on <a href="https://github.com/yi-editor/yi/issues/">GitHub</a>. Please note that some of these are documentation bugs: Yi suffers from poor documentation and I believe that’s what the main problems in gaining developers and users has been. When time or area I’m working on allows, missing documentation will be written.</p>
<p>If I find any issue that have been fixed or are no longer applicable, the reports will simply be closed. The issues are very varied: unicode problems, keymap problems, highlighter problems, reloading problems, testing problems, mode problems… There is certainly enough work to entertain anyone for a longer amount of time while making Yi visibly better.</p>
<p>The list of issues is simply an indicator of which problems the second goal of the project will concentrate on, rather than as a promise of which bugs are guaranteed to be fixed by the end of it.</p>
<p>Alongside this goal, I’ll write any modes for Yi as I find time for them. The completion of concurrency part of the project allows us to write many of the modes frequently requested by people wishing to use Yi which are currently impossible/unfeasible to write.</p></li>
<li><p>What deliverables do you think are reasonable targets? Can you outline an approximate schedule of milestones?</p>
<p>The plan is based on the GSoC time line: 20 April - 19 May – while this is a bonding period, I’m already a part of the Yi community and have a fair grasp of it. I’d start to look into this project as early as this period (and in fact I plan to make steps towards it before this date which means some of the outlined issues might get fixed early ;) ).</p>
<p>19 May - 23 June – coding period; by this point I expect to have decided on which concurrency model we’ll use and have a good idea of how it’ll be implemented. By the end of this period, concurrency should either be completed or nearly done, depending on any unexpected problems that might come up. The deliverable would be Yi with (at least some) concurrency support.</p>
<p>24 June - 11 August – second part of the coding period; work on any of the listed (or unlisted bugs) and finish up concurrency if it is still not done. Write extra Yi modes, libraries and documentation as time allows.</p>
<p>11 August - 18 August – post-coding period; write any missing documentation, promote any cool new stuff we wrote ;) While I can not think of a specific deliverable, many bugs should now be fixed, Yi should have a lot more documentation, tests and modes.</p>
<p>As a final note regarding the time line, it is not strictly necessary that the project implements concurrency first: while some bugs might need such support, many simply do not. If it’s convenient to fix something that I had originally planned to for the second part of the project, I’ll do so.</p></li>
<li><p>What relevant experience do you have? e.g. Have you coded anything in Haskell? Have you contributed to any other open source software? Been studying advanced courses in a related topic?</p>
<p>Second year CS student. I program on regular basis using Haskell. I contribute to a bunch of FOSS projects as it seems necessary (see <a href="https://github.com/Fuuzetsu">my GitHub</a>). I have successfully completed GSOC in 2013 which involved working on Haddock. To this day I help out with Haddock which often involves looking at the large GHC code base.</p></li>
<li><p>In what ways do you envisage interacting with the wider Haskell community during your project? e.g. How would you seek help on something your mentor wasn’t able to deal with? How will you get others interested in what you are doing?</p>
<p>I have a <a href="http://fuuzetsu.co.uk/blog">blog</a> which gets propagated onto Haskell Planet. I’m active on IRC and many Haskell-related mailing lists. IRC, mailing lists and any relevant literature is where I’d seek help were I to get stuck on something my mentor can’t help me with. I find that news about Yi are very popular and get propagated by the community itself very easily so I doubt there will be any problem getting people interested.</p>
<p>I’m very easily reachable over e-mail and IRC and all the development is done in public.</p></li>
<li><p>Why do you think you would be the best person to tackle this project?</p>
<p>I’ve been interested in Yi for a couple of months and have already wrote some commits, closed quite a few issues and filed even more issues on my own. I have access to the Yi repository and I help anyone looking to get started with Yi. I have about 2 years of Haskell experience and had my fair share of staring at library code.</p>
<p>As mentioned before, I’m active as a member of the community and help out with one of the core Haskell projects (Haddock).</p></li>
</ul>
]]></summary>
</entry>
<entry>
    <title>Hackage documentation v2</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2014-01-06-Hackage-documentation-v2.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2014-01-06-Hackage-documentation-v2.html</id>
    <published>2014-01-06T23:18:07Z</published>
    <updated>2014-01-06T23:18:07Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on January  6, 2014
    
        by Fūzetsu
    
</div>

<p>This is just a quick follow up to my yesterday’s post (Actually looking at the date, it was this morning. My sleep ‘schedule’ is all over.).</p>
<p>Here are a few issues with <a href="http://fuuzetsu.co.uk/blog/posts/2014-01-06-Fix-your-Hackage-documentation.html">yesterday’s post</a>:</p>
<ol type="1">
<li>My instructions stated <code>cd dist/doc</code> instead of <code>cd dist/doc/html</code></li>
<li>Documentation generated with my instructions would not have package cross-linking (very important). The links would have your local file-system paths instead.</li>
<li>Documentation generated with my instructions would not have the /proper/ Contents page when clicked on a link from documentation. It would still have the Contents page, just not the one generated by Hackage.</li>
</ol>
<p>Here are the fixes to each problem:</p>
<ol type="1">
<li><p>Replace the bad <code>cd</code> path. I have reflected this in the small Bash script I published yesterday <a href="https://gist.github.com/Fuuzetsu/8276421">as a Gist</a> and <a href="http://fuuzetsu.co.uk/misc/hackagedocs">as a file</a>. I did hear that some people were struggling with it a bit (such as on OS X) so if it doesn’t work out of the box, please make educated edits as you see fit.</p></li>
<li><p>You can generate links to the packages with docs already on Hackage by passing an extra flag to <code>cabal haddock</code>. It is</p>
<p><code>--html-location='http://hackage.haskell.org/package/$pkg/docs'</code></p>
<p>Make sure you include <code>$pkg</code> verbatim, Cabal handles it automatically.</p></li>
<li><p>As above, we just need to add an extra <code>cabal haddock</code> flag:</p>
<p><code>--contents-location='http://hackage.haskell.org/package/$pkg'</code></p></li>
</ol>
<p>If there are any further mistakes, please <a href="http://fuuzetsu.co.uk/blog/contact.html">let me know</a> and I’ll post up corrections.</p>
<p>If you have a better script for doing the uploads, also let me know and I’ll be happy to post it up if you want me to. Easy improvements would be to get the package version and package name from the cabal file.</p>
<p><a href="http://fuuzetsu.co.uk/images/shana_kimono_service.jpeg">Fan service</a>.</p>
]]></summary>
</entry>
<entry>
    <title>Fix your Hackage documentation</title>
    <link href="http://fuuzetsu.co.uk/blog/posts/2014-01-06-Fix-your-Hackage-documentation.html" />
    <id>http://fuuzetsu.co.uk/blog/posts/2014-01-06-Fix-your-Hackage-documentation.html</id>
    <published>2014-01-06T01:17:13Z</published>
    <updated>2014-01-06T01:17:13Z</updated>
    <summary type="html"><![CDATA[<div class="info">
    Posted on January  6, 2014
    
        by Fūzetsu
    
</div>

<p>This is a friendly reminder to fix your Hackage documentation.</p>
<p>I’ve been feeling that over the last couple of months, I had to click on an older version of the package far more than before. Considering the Hackage 2 move around August, that was the first suspect. A quick chat in <code>#hackage</code> and it seems I was not the only one with that feeling, although no one could tell me what exactly was wrong.</p>
<p>Before I could went off on the mailing lists and asked for answers, I needed some numbers. People like numbers. If you’re not interested in this post, I ask that you at least read <a href="http://www.haskell.org/pipermail/cabal-devel/2014-January/009629.html">this thread on cabal-devel</a>. Make sure you read the replies as I show how to do some things you might find useful.</p>
<p>Last night a scraped documentation information for the most recent version of all packages on Hackage. I do not have any more access to Hackage than most mere mortals do so this was the only way. <a href="http://hackage.haskell.org/api">Hackage API</a> does exist but is very badly documented and it doesn’t seem to do JSON ever though it claims to do so and the <a href="https://github.com/haskell/hackage-server/issues/11#issuecomment-31593476">relevant GitHub task</a> is on ex-TODO. I used HXT to parse the output pages. You can see the hacky code <a href="https://gist.github.com/Fuuzetsu/8276445">as a Gist</a> or <a href="http://fuuzetsu.co.uk/misc/H.hs">as a file</a>.</p>
<p>So considering this is a reminder, I better provide some information. You can find a list of package uploaded in 2013 and 2014 for which the documentation was deemed broken <a href="http://fuuzetsu.co.uk/misc/sorted.txt">by clicking this</a>. There are multiple reasons why a package could fail. To reiterate from the e-mail I sent to the mailing lists, here are failures we can’t do that much about:</p>
<ul>
<li>Dependencies fail to build so your package does</li>
<li>Your package fails to build directly</li>
<li>Your package requires non-cabal libraries which aren’t installed</li>
<li>Your package requires different version of install libraries</li>
</ul>
<p>There are however failures you can do something about straight away: Haddock failures. If your package was listed <a href="http://fuuzetsu.co.uk/misc/sorted.txt">here</a> and had ‘InstallOk’ next to it, your Haddock comments are probably wrong. This means you should view the build log and see what’s wrong.</p>
<h2 id="viewing-the-hackage-build-log">Viewing the Hackage build log</h2>
<p>Here’s a very poorly but useful feature of Hackage: you can usually view your build log. If on my list, you have a MissingDocs reason that’s not ‘Nothing’, you can view this log. If it’s Nothing, sorry but you’re out of luck. See <a href="https://github.com/haskell/hackage-server/issues/145#issuecomment-30129142">this comment</a> on what is happening. I will show you how to upload documentation manually later for these cases.</p>
<ol type="1">
<li>Identify your package version. My list shows this but you should also be able to just go on Hackage and see what’s broken. As an example, I’ll be using my tiny yi-monokai-0.1.1.1 package for which the build has failed.</li>
<li>Read the build log. You can get the build status for Hackage packages like so: <a href="http://hackage.haskell.org/package/yi-monokai-0.1.1.1/reports/" class="uri">http://hackage.haskell.org/package/yi-monokai-0.1.1.1/reports/</a>. Considering your package got InstallOk, this will exist. You can go to the first build status log like so: <a href="http://hackage.haskell.org/package/yi-monokai-0.1.1.1/reports/1" class="uri">http://hackage.haskell.org/package/yi-monokai-0.1.1.1/reports/1</a> and you can get to the actual build log like this: <a href="http://hackage.haskell.org/package/yi-monokai-0.1.1.1/reports/1/log" class="uri">http://hackage.haskell.org/package/yi-monokai-0.1.1.1/reports/1/log</a>. The pattern should be easy to spot.</li>
</ol>
<p>Somewhere at the bottom of the build log there should be a reason for failure. If it’s a Haddock error, fix it. I made your job easier and made <a href="http://fuuzetsu.co.uk/misc/faileddocs.txt">a list of packages which seem to simply have malformed Haddock comments</a>. I had manually fixed and formed pull request for the bottom third of these. It’s usually very easy to fix! See <a href="http://www.haskell.org/haddock/doc/html/">Haddock manual</a> for help on syntax. You can also ping me on IRC (Fuuzetsu) and I’ll be happy to point out what might be wrong.</p>
<p>Another kind of failure one might get this way is HsColour failure: Hackage can run Haddock with <code>--hyperlink-source</code> and I saw an error yesterday caused by bad file encoding and HsColour failing. This is unusual (your files should be UTF-8 to begin with).</p>
<p>If all it is a Haddock parse error, simply fix it and upload a new version of the package. Anyone browsing will be grateful!</p>
<p>If it’s something else, read on.</p>
<h2 id="uploading-documentation-manually">Uploading documentation manually</h2>
<p>If your failure wasn’t a simple Haddock markup problem, it might not be plausible to have Hackage build your documentation. An easy example is missing C libraries. While ideally Hackage should have means of providing these, it currently doesn’t.</p>
<p>If you don’t have a build log for your package (‘Nothing’ on my list), this is probably the only way to get documentation too.</p>
<p>Here I’ll outline how to create and upload documentation by hand for your package. The change should immediate once uploaded.</p>
<p>Before you do this, check your build log. If it’s just a Haddock failure, fix it and upload the package afresh. Don’t upload documentation which differs from the actual package version.</p>
<p>You first need to make your documentation. I’ll be using ‘yi-monokai-0.1.1.1’ package as an example.</p>
<ol type="1">
<li><p>Navigate to your project’s directory:</p>
<p><code>cd ~/programming/yi-monokai</code></p></li>
<li><p>Build package with documentation:</p>
<p><code>cabal configure &amp;&amp; cabal build &amp;&amp; cabal haddock   --hyperlink-source</code></p></li>
<li><p>Navigate to where your documentation was generated.</p>
<p><code>cd dist/doc</code></p></li>
<li><p>Rename your docs directory to a format Hackage expects it in. It is ‘packagename-version-docs’.</p>
<p><code>mv yi-monokai yi-monokai-0.1.1.1-docs</code></p></li>
<li><p>Create an archive of your directory. It has to be in a specific format and you’ll need the <code>--format=ustar</code> flag.</p>
<p><code>tar -c -v -z -Hustar -f yi-monokai-0.1.1.1-docs.tar.gz   yi-monokai-0.1.1.1-docs</code></p></li>
<li><p>Upload the docs to Hackage. You need to make a POST to a specific URL. Triple check your package version: you don’t want to be uploading documentation for the wrong thing. The username and password are your Hackage credentials.</p>
<p><code>curl -X PUT -H 'Content-Type: application/x-tar' -H   'Content-Encoding: gzip' --data-binary   '@yi-monokai-0.1.1.1-docs.tar.gz'   'http://USERNAME:PASSWORD@hackage.haskell.org/package/yi-monokai-0.1.1.1/docs'</code></p></li>
<li><p>Go on Hackage and see whether it worked. Your docs should come up straight away. If they haven’t, worry. Check your URL. Make sure you didn’t get any error messages from Hackage when uploading the package.</p></li>
</ol>
<p>Here’s a quick Bash script to automate it a bit: <a href="https://gist.github.com/Fuuzetsu/8276421">as a Gist</a> or <a href="http://fuuzetsu.co.uk/misc/hackagedocs">as a file</a>. Perhaps a library to interface with Hackage needs to be written. In fact, that’d be pretty useful. Put it somewhere in your PATH, go into your project’s directory and use it like this:</p>
<p><code>hackagedocs yi-monokai 0.1.1.1 username password</code></p>
<p>It’s is very naive, I am in fact writing it while I’m writing this blog post. Please adjust the commands inside as you see necessary.</p>
<p>Disclaimer: I don’t know Bash, I’m just making stuff up from snippets of scripts I have lying around.</p>
<p>I hope I encouraged you to make your Hackage documentation work again! Have <a href="http://fuuzetsu.co.uk/images/shana_meronpan.jpeg">some fan service</a> for making it all the way to the end of the tedious post.</p>
<p>EDIT: See updates to this post <a href="http://fuuzetsu.co.uk/blog/posts/2014-01-06-Hackage-documentation-v2.html">here</a>, it tells you how to fix package cross-linking and stuff. Also, please keep reading <a href="http://www.haskell.org/pipermail/cabal-devel/2014-January/009629.html">the mailing list thread</a> for further developments. Nice people post their scripts to do this stuff and in general these issues are discussed.</p>
]]></summary>
</entry>

</feed>
