her.esy.fun/src/Scratch/fr/blog/feed/feed.xml

5662 lines
349 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>yannesposito.com</title>
<link href="http://yannesposito.com/Scratch/fr/blog/feed/feed.xml" rel="self" />
<link href="http://yannesposito.com" />
<id>http://yannesposito.com/Scratch/fr/blog/feed/feed.xml</id>
<author>
<name>Yann Esposito</name>
<email>yann.esposito@gmail.com</email>
</author>
<updated>2016-10-01T00:00:00Z</updated>
<entry>
<title>Tips in avoiding Haskell Success at all cost</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Helping-avoid-Haskell-Success/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Helping-avoid-Haskell-Success/index.html</id>
<published>2016-10-01T00:00:00Z</published>
<updated>2016-10-01T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Helping-avoid-Haskell-Success/main.jpg" alt="Main image"/>
</div>
<div class="intro">
<p>Few days ago there were about 20 job offer for Haskell. In only one day! How is that possible? As a <strong>real</strong> haskeller, I find this situation unbearable!</p>
<p>After all, we must <em>avoid success at all cost</em>. And Ill help SPJ achieve this honorable goal.</p>
</div>
<h2 id="prevent-interest-from-beginner">Prevent Interest from beginner</h2>
<p>Imagine a situation were you see people demonstrating some interest in learning Haskell.</p>
<p>Quick! Prevent them from going further.</p>
<p>If they come from the dynamic (uni-typed) languages like Python, Javascript…:</p>
<blockquote>
<p>Haskell? A statically typed language??? Hmm… You mean like C and Java?</p>
</blockquote>
<p>Such a remark should immediately shut down any interest in Haskell.</p>
<p>If they want to produce application with them:</p>
<blockquote>
<p>Haskell? Isnt it only a language for student! I dont think it is useful for <em>REAL WORLD</em> applications!</p>
</blockquote>
<p>If they just want to learn something new:</p>
<blockquote>
<p>Haskell? Ah yes, I remember, mostly they only have the equivalent of Java interfaces and they stopped there. They dont even have classes!!!! Can you imagine? I dont even speak about class inheritance.</p>
<p>Were in 2016! And they dont even support basic Object Oriented Programming. What a joke!</p>
</blockquote>
<p>If they love low level programming:</p>
<blockquote>
<p>Haskell? Ah yes, I heard that lazyness make it impossible to think about code complexity and generally cause lot of space leaks.</p>
</blockquote>
<p>And if it is not enough:</p>
<blockquote>
<p>Haskell? Ah yes. Im not fan of their Stop the World GC.</p>
</blockquote>
<p>If they come from LISP and the statically typed language remark wasnt enough. Try to mention the lack of macros in Haskell. Dont mention template Haskell or even less Generics and all recent progress in GHC.</p>
<h2 id="make-it-difficult-to-install">Make it difficult to install</h2>
<p>Many hints there:</p>
<ul>
<li>Send them on another compiler than GHC</li>
<li>Explain that they should never use a binary distribution of GHC! And they must compile it manually! It might not stop them but it will make the installation process much more tedious.</li>
<li>Lie! Explain there is a severe security issue with latest tools. Explain they must use cabal-install 1.18 or older.</li>
<li>Also explain them that in order to be able to handle lib dependencies correctly they <strong>MUST</strong> first learn Nix! Never talk about <code>stack</code>, <code>cabal freeze</code>, … While Nix is great, forcing new user completely alien to all these concepts to first learn it before starting to write their first line of code can greatly reduce their enthusiasm. Bonus point if you make them believe you can only program in Haskell on NixOS.</li>
</ul>
<h2 id="make-it-difficult-to-learn">Make it difficult to learn</h2>
<h3 id="make-new-comers-feel-dumb">Make new comers feel dumb</h3>
<p>The very first thing to do is to explain how Haskell is so easy to learn. How natural it is for everybody you know. And except someone you always considered very dumb, everybody was very productive in Haskell in few hours.</p>
<p>Use vocabulary alien to them as much as possible. Here is a list of terms you should use in the very first minutes of your description of Haskell:</p>
<ul>
<li>catamorphism (bonus if you mention that the word come from the Greek κατα for catastrophe, that way youll look like a snob and you also use the word catastrophe in a Haskell context).</li>
<li>Monad! Of course you should use it ASAP! And explain they are exactly like potatoes or bananas shaped chairs. Double bonus if you explain that monad are really simple as they are just a monoid in the category of endofunctors.</li>
<li>GADTs</li>
<li>Yoneda Lemma</li>
<li>Homotopy Type Theory</li>
<li>…</li>
</ul>
<p>Each of this term will hopefully be intimidating.</p>
<h3 id="tutorial-authors">Tutorial authors</h3>
<p>Please dont provide an obvious first example like:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" title="1">main <span class="ot">=</span> <span class="fu">putStrLn</span> <span class="st">&quot;Hello World!&quot;</span></a></code></pre></div>
<p>Instead prefer a fully servant example:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb2-1" title="1"><span class="ot">{-# LANGUAGE DataKinds #-}</span></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="ot">{-# LANGUAGE DeriveGeneric #-}</span></a>
<a class="sourceLine" id="cb2-3" title="3"><span class="ot">{-# LANGUAGE LambdaCase #-}</span></a>
<a class="sourceLine" id="cb2-4" title="4"><span class="ot">{-# LANGUAGE TypeOperators #-}</span></a>
<a class="sourceLine" id="cb2-5" title="5"></a>
<a class="sourceLine" id="cb2-6" title="6"><span class="kw">module</span> <span class="dt">App</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb2-7" title="7"></a>
<a class="sourceLine" id="cb2-8" title="8"><span class="kw">import</span> <span class="dt">Control.Monad.Trans.Except</span></a>
<a class="sourceLine" id="cb2-9" title="9"><span class="kw">import</span> <span class="dt">Data.Aeson</span></a>
<a class="sourceLine" id="cb2-10" title="10"><span class="kw">import</span> <span class="dt">GHC.Generics</span></a>
<a class="sourceLine" id="cb2-11" title="11"><span class="kw">import</span> <span class="dt">Network.Wai</span></a>
<a class="sourceLine" id="cb2-12" title="12"><span class="kw">import</span> <span class="dt">Network.Wai.Handler.Warp</span></a>
<a class="sourceLine" id="cb2-13" title="13"><span class="kw">import</span> <span class="dt">Servant</span></a>
<a class="sourceLine" id="cb2-14" title="14"><span class="kw">import</span> <span class="dt">System.IO</span></a>
<a class="sourceLine" id="cb2-15" title="15"></a>
<a class="sourceLine" id="cb2-16" title="16"><span class="kw">type</span> <span class="dt">ItemApi</span> <span class="ot">=</span></a>
<a class="sourceLine" id="cb2-17" title="17"> <span class="st">&quot;item&quot;</span> <span class="op">:&gt;</span> <span class="dt">Get</span> &#39;[<span class="dt">JSON</span>] [<span class="dt">Item</span>] <span class="op">:&lt;|&gt;</span></a>
<a class="sourceLine" id="cb2-18" title="18"> <span class="st">&quot;item&quot;</span> <span class="op">:&gt;</span> <span class="dt">Capture</span> <span class="st">&quot;itemId&quot;</span> <span class="dt">Integer</span> <span class="op">:&gt;</span> <span class="dt">Get</span> &#39;[<span class="dt">JSON</span>] <span class="dt">Item</span></a>
<a class="sourceLine" id="cb2-19" title="19"></a>
<a class="sourceLine" id="cb2-20" title="20"><span class="ot">itemApi ::</span> <span class="dt">Proxy</span> <span class="dt">ItemApi</span></a>
<a class="sourceLine" id="cb2-21" title="21">itemApi <span class="ot">=</span> <span class="dt">Proxy</span></a>
<a class="sourceLine" id="cb2-22" title="22"></a>
<a class="sourceLine" id="cb2-23" title="23"><span class="ot">run ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb2-24" title="24">run <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb2-25" title="25"> <span class="kw">let</span> port <span class="ot">=</span> <span class="dv">3000</span></a>
<a class="sourceLine" id="cb2-26" title="26"> settings <span class="ot">=</span></a>
<a class="sourceLine" id="cb2-27" title="27"> setPort port <span class="op">$</span></a>
<a class="sourceLine" id="cb2-28" title="28"> setBeforeMainLoop (hPutStrLn stderr (<span class="st">&quot;listening on port &quot;</span> <span class="op">++</span> <span class="fu">show</span> port)) <span class="op">$</span></a>
<a class="sourceLine" id="cb2-29" title="29"> defaultSettings</a>
<a class="sourceLine" id="cb2-30" title="30"> runSettings settings <span class="op">=&lt;&lt;</span> mkApp</a>
<a class="sourceLine" id="cb2-31" title="31"></a>
<a class="sourceLine" id="cb2-32" title="32"><span class="ot">mkApp ::</span> <span class="dt">IO</span> <span class="dt">Application</span></a>
<a class="sourceLine" id="cb2-33" title="33">mkApp <span class="ot">=</span> <span class="fu">return</span> <span class="op">$</span> serve itemApi server</a>
<a class="sourceLine" id="cb2-34" title="34"></a>
<a class="sourceLine" id="cb2-35" title="35"><span class="ot">server ::</span> <span class="dt">Server</span> <span class="dt">ItemApi</span></a>
<a class="sourceLine" id="cb2-36" title="36">server <span class="ot">=</span></a>
<a class="sourceLine" id="cb2-37" title="37"> getItems <span class="op">:&lt;|&gt;</span></a>
<a class="sourceLine" id="cb2-38" title="38"> getItemById</a>
<a class="sourceLine" id="cb2-39" title="39"></a>
<a class="sourceLine" id="cb2-40" title="40"><span class="kw">type</span> <span class="dt">Handler</span> <span class="ot">=</span> <span class="dt">ExceptT</span> <span class="dt">ServantErr</span> <span class="dt">IO</span></a>
<a class="sourceLine" id="cb2-41" title="41"></a>
<a class="sourceLine" id="cb2-42" title="42"><span class="ot">getItems ::</span> <span class="dt">Handler</span> [<span class="dt">Item</span>]</a>
<a class="sourceLine" id="cb2-43" title="43">getItems <span class="ot">=</span> <span class="fu">return</span> [exampleItem]</a>
<a class="sourceLine" id="cb2-44" title="44"></a>
<a class="sourceLine" id="cb2-45" title="45"><span class="ot">getItemById ::</span> <span class="dt">Integer</span> <span class="ot">-&gt;</span> <span class="dt">Handler</span> <span class="dt">Item</span></a>
<a class="sourceLine" id="cb2-46" title="46">getItemById <span class="ot">=</span> \ <span class="kw">case</span></a>
<a class="sourceLine" id="cb2-47" title="47"> <span class="dv">0</span> <span class="ot">-&gt;</span> <span class="fu">return</span> exampleItem</a>
<a class="sourceLine" id="cb2-48" title="48"> _ <span class="ot">-&gt;</span> throwE err404</a>
<a class="sourceLine" id="cb2-49" title="49"></a>
<a class="sourceLine" id="cb2-50" title="50"><span class="ot">exampleItem ::</span> <span class="dt">Item</span></a>
<a class="sourceLine" id="cb2-51" title="51">exampleItem <span class="ot">=</span> <span class="dt">Item</span> <span class="dv">0</span> <span class="st">&quot;example item&quot;</span></a>
<a class="sourceLine" id="cb2-52" title="52"></a>
<a class="sourceLine" id="cb2-53" title="53"><span class="kw">data</span> <span class="dt">Item</span></a>
<a class="sourceLine" id="cb2-54" title="54"> <span class="ot">=</span> <span class="dt">Item</span> {</a>
<a class="sourceLine" id="cb2-55" title="55"><span class="ot"> itemId ::</span> <span class="dt">Integer</span>,</a>
<a class="sourceLine" id="cb2-56" title="56"><span class="ot"> itemText ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb2-57" title="57"> }</a>
<a class="sourceLine" id="cb2-58" title="58"> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Generic</span>)</a>
<a class="sourceLine" id="cb2-59" title="59"></a>
<a class="sourceLine" id="cb2-60" title="60"><span class="kw">instance</span> <span class="dt">ToJSON</span> <span class="dt">Item</span></a>
<a class="sourceLine" id="cb2-61" title="61"><span class="kw">instance</span> <span class="dt">FromJSON</span> <span class="dt">Item</span></a></code></pre></div>
<p>This nice example should overflow the number of new concepts a Haskell newcomer should deal with:</p>
<ul>
<li>Language extensions. Each extension can take a lot of time to be explained.</li>
<li>Strange notations:
<ul>
<li><code>:&lt;|&gt;</code></li>
<li><code>'[]</code> instead of <code>[]</code></li>
</ul></li>
<li><code>Proxy</code></li>
<li>Immediate usage of <code>$</code></li>
<li><code>deriving</code> ha ha! Youll need to explain typeclasses first!</li>
<li>the definition for <code>getItemById</code></li>
</ul>
<p>Of course use the most of your energy explaining the language extensions first. Use a great deal of details and if possible use as much as possible references to Category Theory. Youll get bonus points if you mention HoTT! Double bonus points if you explain that understanding all details in HoTT is essential to use Haskell on a daily basis.</p>
<p>Explain that what this does is incredible but for the wrong reasons. For example dont mention why <code>instance ToJSON Item</code> is great. But insist that we achieved to serve a JSON with extreme elegance and simplicity. Keep insisting on the simplicity and forgot to mention type safety which is one of the main benefit of Servant.</p>
<p>If youre afraid that this example might be too close to a real world product, you can simply use some advanced lenses examples:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb3-1" title="1"><span class="ot">{-# LANGUAGE DeriveGeneric #-}</span></a>
<a class="sourceLine" id="cb3-2" title="2"><span class="ot">{-# LANGUAGE TemplateHaskell #-}</span></a>
<a class="sourceLine" id="cb3-3" title="3"></a>
<a class="sourceLine" id="cb3-4" title="4"><span class="kw">import</span> <span class="dt">Control.Lens.TH</span> (makePrisms)</a>
<a class="sourceLine" id="cb3-5" title="5"><span class="kw">import</span> <span class="dt">GHC.Generics</span> (<span class="dt">Generic</span>)</a>
<a class="sourceLine" id="cb3-6" title="6"><span class="kw">import</span> <span class="dt">Lens.Family.Total</span></a>
<a class="sourceLine" id="cb3-7" title="7"></a>
<a class="sourceLine" id="cb3-8" title="8"><span class="kw">data</span> <span class="dt">Example</span> a b c <span class="ot">=</span> <span class="dt">C1</span> a <span class="op">|</span> <span class="dt">C2</span> b <span class="op">|</span> <span class="dt">C3</span> c <span class="kw">deriving</span> (<span class="dt">Generic</span>)</a>
<a class="sourceLine" id="cb3-9" title="9"></a>
<a class="sourceLine" id="cb3-10" title="10">makePrisms &#39;<span class="dt">&#39;Example</span></a>
<a class="sourceLine" id="cb3-11" title="11"></a>
<a class="sourceLine" id="cb3-12" title="12"><span class="kw">instance</span> (<span class="dt">Empty</span> a, <span class="dt">Empty</span> b, <span class="dt">Empty</span> c) <span class="ot">=&gt;</span> <span class="dt">Empty</span> (<span class="dt">Example</span> a b c)</a>
<a class="sourceLine" id="cb3-13" title="13"></a>
<a class="sourceLine" id="cb3-14" title="14"><span class="ot">example ::</span> <span class="dt">Example</span> <span class="dt">String</span> <span class="dt">Char</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb3-15" title="15">example <span class="ot">=</span> _case</a>
<a class="sourceLine" id="cb3-16" title="16"> <span class="op">&amp;</span> on _C1 (\s <span class="ot">-&gt;</span> s )</a>
<a class="sourceLine" id="cb3-17" title="17"> <span class="op">&amp;</span> on _C2 (\c <span class="ot">-&gt;</span> <span class="fu">replicate</span> <span class="dv">3</span> c )</a>
<a class="sourceLine" id="cb3-18" title="18"> <span class="op">&amp;</span> on _C3 (\n <span class="ot">-&gt;</span> <span class="fu">replicate</span> n <span class="ch">&#39;!&#39;</span>)</a></code></pre></div>
<p>Certainly a great example to start a new language with.</p>
<h3 id="library-authors">Library authors</h3>
<ol type="1">
<li>Do your best not to respect versioning number policy to maximize the probability to break things.</li>
<li>Dont write any documentation, type are enough!</li>
<li>Even better, add mistakes to your documentation</li>
<li>Each time you can use a meaningful notation, make it wrong. For example, if you have a symmetric relation use an asymmetric symbol to represent it.</li>
<li>If possible remove all function names and only use symbols of at least 5 letters: For example you can replace your function <code>log :: Level -&gt; String -&gt; IO ()</code> by <code>(&lt;=.=$$.)</code>.</li>
</ol>
<p>If the the trends continue toward growth, then we might need to go further at the risk of breaking our own ecosystem:</p>
<ul>
<li>Split your libs as much as possible. The best would be to use one lib by symbol</li>
<li>Use <code>unsafePerformIO</code> as much as possible</li>
<li>Push to Hackage a version not accessible on your public repository</li>
<li>modify the package on Hackage using the same version but with incompatible API</li>
<li>Add memory leaks</li>
<li>Add bugs</li>
<li>Add back doors and publish how to use them</li>
</ul>
<p>Yes we said, <em>at all cost</em>!</p>
<h2 id="conclusion-mistake">Conclusion &amp; Mistake</h2>
<p>So with all of this I believe we should be on the right track to avoid success at all cost!</p>
<p>Sorry? What?</p>
<p>Oh… Apparently I made a precedence mistake!</p>
<p>SPJ didnt asked to <code>avoid success $ at all cost</code> but to <code>avoid $ success at all cost</code><a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a>.</p>
<p>Sorry! My bad! Forget about all of this. Keep the good work everybody! Haskell is certainly one of the most awesome language in the world! Its community is also just great.</p>
<p>Im really happy to see it growth every year. Thanks to all contributors making it possible to still have a lot of fun after many years using Haskell!</p>
<p>And the fact that in Haskell the <em>right</em> choice is preferred to the easiest choice, certainly helped.</p>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>A good point to use more LISP syntax.<a href="#fnref1" class="footnote-back">↩</a></p></li>
</ol>
</section>]]></summary>
</entry>
<entry>
<title>Haskell Tutorials, a tutorial</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Haskell-Tutorials--a-tutorial/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Haskell-Tutorials--a-tutorial/index.html</id>
<published>2016-05-06T00:00:00Z</published>
<updated>2016-05-06T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Haskell-Tutorials--a-tutorial/main.jpg" alt="Main image"/>
</div>
<div class="intro">
<p><span class="sc"><abbr title="Too long; didn't read">tl;dr</abbr>: </span> Some hints on how to make great documentation for Haskell libraries.</p>
<ol type="1">
<li>Create a <code>Tutorial</code> module containing nothing except documentation.</li>
<li>Mention the <code>Tutorial</code> module in your <code>cabal</code> description</li>
<li>Use <code>doctest</code> to check your documentation is up to date</li>
<li>For more complex real world examples, link to the source of some test.</li>
</ol>
</div>
<p>Great documentation make a big difference. A bad documentation could simply make people not using your lib.</p>
<p>My friend was learning Haskell. To start he tried a Haskell library to make a small application. The documentation was deprecated to the point he wasnt able to make a basic example work. How do you believe he felt? What does he thought about Haskell in general?</p>
<p>So here are my hint on how to make a great documentation in Haskell.</p>
<p>Documentation can take many different form.</p>
<ol type="1">
<li><strong>Tutorials/Guides</strong> write some prose which friendly take a user by hand and help him</li>
<li><strong>Examples</strong> how to use each function</li>
<li><strong>Generated API Documentation</strong> haddock</li>
</ol>
<h2 id="hints">Hints</h2>
<h3 id="tutorialsguides">Tutorials/Guides</h3>
<ol type="1">
<li>Create a new module named <code>Tutorial</code> (or <code>Guide.GuideTopic</code>)</li>
<li>Create a link to the tutorial in the cabal description</li>
<li>Create a link to the tutorial in your README</li>
<li>Here is an example some <code>Tutorial</code> module content:</li>
</ol>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" title="1"><span class="ot">{-# OPTIONS_GHC -fno-warn-unused-imports #-}</span></a>
<a class="sourceLine" id="cb1-2" title="2"><span class="co">{-|</span></a>
<a class="sourceLine" id="cb1-3" title="3"><span class="co"> Use @my-package@ if you want to ...</span></a>
<a class="sourceLine" id="cb1-4" title="4"><span class="co">-}</span></a>
<a class="sourceLine" id="cb1-5" title="5"><span class="kw">module</span> <span class="dt">Data.Duration.Tutorial</span> (</a>
<a class="sourceLine" id="cb1-6" title="6"></a>
<a class="sourceLine" id="cb1-7" title="7"> <span class="co">-- * Introduction</span></a>
<a class="sourceLine" id="cb1-8" title="8"> <span class="co">-- $introduction</span></a>
<a class="sourceLine" id="cb1-9" title="9"></a>
<a class="sourceLine" id="cb1-10" title="10"> <span class="co">-- ** Subsection</span></a>
<a class="sourceLine" id="cb1-11" title="11"> <span class="co">-- $subsection</span></a>
<a class="sourceLine" id="cb1-12" title="12"></a>
<a class="sourceLine" id="cb1-13" title="13"> ) <span class="kw">where</span></a>
<a class="sourceLine" id="cb1-14" title="14"></a>
<a class="sourceLine" id="cb1-15" title="15"><span class="kw">import</span> <span class="dt">Data.Duration</span></a>
<a class="sourceLine" id="cb1-16" title="16"></a>
<a class="sourceLine" id="cb1-17" title="17"><span class="co">{- $introduction</span></a>
<a class="sourceLine" id="cb1-18" title="18"></a>
<a class="sourceLine" id="cb1-19" title="19"><span class="co">So here how you use it:</span></a>
<a class="sourceLine" id="cb1-20" title="20"></a>
<a class="sourceLine" id="cb1-21" title="21"><span class="co"> &gt;&gt;&gt; humanReadableDuration 1002012.002</span></a>
<a class="sourceLine" id="cb1-22" title="22"><span class="co"> &quot;11 days 14 hours 20 min 12s 2ms&quot;</span></a>
<a class="sourceLine" id="cb1-23" title="23"></a>
<a class="sourceLine" id="cb1-24" title="24"><span class="co">The function is &#39;humanReadableDuration&#39; and</span></a>
<a class="sourceLine" id="cb1-25" title="25"><span class="co">the you&#39;ll be able to click on it to go</span></a>
<a class="sourceLine" id="cb1-26" title="26"><span class="co">to its definition.</span></a>
<a class="sourceLine" id="cb1-27" title="27"></a>
<a class="sourceLine" id="cb1-28" title="28"><span class="co">You can add images: &lt;&lt;path-to-image.png title&gt;&gt;</span></a>
<a class="sourceLine" id="cb1-29" title="29"><span class="co">and links: &lt;http://haskell-lang.org haskell&gt;.</span></a>
<a class="sourceLine" id="cb1-30" title="30"><span class="co"> </span></a>
<a class="sourceLine" id="cb1-31" title="31"><span class="co">-}</span></a>
<a class="sourceLine" id="cb1-32" title="32"></a>
<a class="sourceLine" id="cb1-33" title="33"><span class="co">{- $subsection</span></a>
<a class="sourceLine" id="cb1-34" title="34"></a>
<a class="sourceLine" id="cb1-35" title="35"><span class="co">This is a chuck of documentation</span></a>
<a class="sourceLine" id="cb1-36" title="36"><span class="co">not attached to any particular Haskell</span></a>
<a class="sourceLine" id="cb1-37" title="37"><span class="co">declaration with an untested code block:</span></a>
<a class="sourceLine" id="cb1-38" title="38"></a>
<a class="sourceLine" id="cb1-39" title="39"><span class="co">&gt; answer = 42</span></a>
<a class="sourceLine" id="cb1-40" title="40"></a>
<a class="sourceLine" id="cb1-41" title="41"><span class="co">-}</span></a></code></pre></div>
<p>To prevent obsolescence of your tutorial, use <code>doctest</code>.</p>
<p>That way when youll do a <code>stack test</code> or <code>cabal test</code> youll get errors if some example doesnt work anymore.</p>
<h3 id="examples-doctest">Examples (doctest)</h3>
<p><code>doctest</code> is a great way to provide examples in your code documentation. These example will then be used as tests. Apparently it comes from Python community.</p>
<p>To use <code>doctest</code>, this is very simple:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb2-1" title="1"><span class="co">-- | My function description</span></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="co">-- </span></a>
<a class="sourceLine" id="cb2-3" title="3"><span class="co">-- &gt;&gt;&gt; myFunction 3 4</span></a>
<a class="sourceLine" id="cb2-4" title="4"><span class="co">-- 7</span></a>
<a class="sourceLine" id="cb2-5" title="5"><span class="ot">myFunction ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></a>
<a class="sourceLine" id="cb2-6" title="6">myFunction <span class="ot">=</span> (<span class="op">+</span>)</a></code></pre></div>
<p>And to make it works simply verify you have a <code>test</code> bloc in your <code>.cabal</code> file looking like this:</p>
<pre><code>test-suite doctest
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: DocTest.hs
build-depend: base &gt;= 4.7 &amp;&amp; &lt; 5
, &lt;YOUR_LIBRARY&gt;
, Glob &gt;= 0.7
, doctest &gt;= 0.9.12</code></pre>
<p>and in <code>test/DocTest.hs</code> simply use</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb4-1" title="1"><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb4-2" title="2"></a>
<a class="sourceLine" id="cb4-3" title="3"><span class="kw">import</span> <span class="dt">DocTest</span></a>
<a class="sourceLine" id="cb4-4" title="4"><span class="kw">import</span> <span class="dt">System.FilePath.Glob</span> (glob)</a>
<a class="sourceLine" id="cb4-5" title="5"></a>
<a class="sourceLine" id="cb4-6" title="6">main <span class="ot">=</span> glob <span class="st">&quot;src/**/*.hs&quot;</span> <span class="op">&gt;&gt;=</span> docTest</a></code></pre></div>
<p>Now <code>stack test</code> or <code>cabal test</code> will check the validity of your documentation.</p>
<h2 id="bonuses">Bonuses</h2>
<h3 id="verifying-documentation-coverage">Verifying documentation coverage</h3>
<ol type="1">
<li>Install haddock <code>stack install haddock</code> or <code>cabal install haddock</code></li>
<li>Launch haddock without output format:</li>
</ol>
<pre><code>&gt; haddock src/**/*.hs
Haddock coverage:
100% ( 15 / 15) in &#39;Data.Duration&#39;
100% ( 3 / 3) in &#39;Data.Duration.Tutorial&#39;</code></pre>
<h3 id="continuous-integration">Continuous Integration</h3>
<p>There are plenty of alternative solution. I provide the one I believe would be used by most people. So if you use <code>github</code> simply create an account on <a href="http://travis-ci.org"><code>travis</code></a>.</p>
<p>Add a <code>.travis.yml</code> file in your repo containing the content of the file <a href="http://docs.haskellstack.org/en/stable/GUIDE/#travis-with-caching">here</a> and remove the builds you dont need. It will build your project using a lot of different GHC versions and environemnts.</p>
<p>If you are afraid by such its complexity you might just want to use this one:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode .yaml"><code class="sourceCode yaml"><a class="sourceLine" id="cb6-1" title="1"><span class="fu">sudo:</span><span class="at"> </span><span class="ch">false</span></a>
<a class="sourceLine" id="cb6-2" title="2"></a>
<a class="sourceLine" id="cb6-3" title="3"><span class="fu">addons:</span></a>
<a class="sourceLine" id="cb6-4" title="4"> <span class="fu">apt:</span></a>
<a class="sourceLine" id="cb6-5" title="5"> <span class="fu">packages:</span></a>
<a class="sourceLine" id="cb6-6" title="6"> <span class="kw">-</span> libgmp-dev</a>
<a class="sourceLine" id="cb6-7" title="7"></a>
<a class="sourceLine" id="cb6-8" title="8"><span class="co"># Caching so the next build will be fast too.</span></a>
<a class="sourceLine" id="cb6-9" title="9"><span class="fu">cache:</span></a>
<a class="sourceLine" id="cb6-10" title="10"> <span class="fu">directories:</span></a>
<a class="sourceLine" id="cb6-11" title="11"> <span class="kw">-</span> $HOME/.stack</a>
<a class="sourceLine" id="cb6-12" title="12"></a>
<a class="sourceLine" id="cb6-13" title="13"><span class="fu">before_install:</span></a>
<a class="sourceLine" id="cb6-14" title="14"><span class="co"># Download and unpack the stack executable</span></a>
<a class="sourceLine" id="cb6-15" title="15"><span class="kw">-</span> mkdir -p ~/.local/bin</a>
<a class="sourceLine" id="cb6-16" title="16"><span class="kw">-</span> export PATH=$HOME/.local/bin:$PATH</a>
<a class="sourceLine" id="cb6-17" title="17"><span class="kw">-</span> travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin <span class="st">&#39;*/stack&#39;</span></a>
<a class="sourceLine" id="cb6-18" title="18"></a>
<a class="sourceLine" id="cb6-19" title="19"><span class="fu">script:</span></a>
<a class="sourceLine" id="cb6-20" title="20"> <span class="kw">-</span> stack setup &amp;&amp; stack --no-terminal --skip-ghc-check test</a></code></pre></div>
<p>Dont forget to activate your repo in travis.</p>
<p>For some bonus points add the build status badge in your <code>README.md</code> file:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode .markdown"><code class="sourceCode markdown"><a class="sourceLine" id="cb7-1" title="1"><span class="ot">[![Build Status](https://travis-ci.org/user-name/project-name.svg?branch=master)</span>](https://travis-ci.org/user-name/project-name)</a></code></pre></div>
<p>Congratulation! Now if you break your documentation examples, youll get notified.</p>
<h3 id="badges">Badges</h3>
<p>You could add badges to your <code>README.md</code> file.</p>
<p>Here is a list of some: <a href="http://shields.io"><code>shields.io</code></a></p>
<h4 id="hackage">Hackage</h4>
<div class="sourceCode" id="cb8"><pre class="sourceCode .markdown"><code class="sourceCode markdown"><a class="sourceLine" id="cb8-1" title="1"><span class="ot">[![Hackage](https://img.shields.io/hackage/v/packagename)</span>](https://hackage.haskell.org/package/packagename)</a></code></pre></div>
<h4 id="stackage">Stackage</h4>
<p>If you didnt declared your package to <code>stackage</code>, please do it. It isnt much work. Just edit a file to add your package. And youll could be able to add another badge:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode .markdown"><code class="sourceCode markdown"><a class="sourceLine" id="cb9-1" title="1"><span class="ot">[![packagename on Stackage LTS](http://stackage.org/package/packagename/badge/lts-3)</span>](http://stackage.org/lts/package/packagename)</a></code></pre></div>
<p>See <a href="https://www.fpcomplete.com/blog/2015/10/stackage-badges">Stackage Badges</a> for more informations.</p>
<h3 id="creating-a-new-project-with-stack">Creating a new project with <code>stack</code></h3>
<p>If you use <code>stack</code> I suggest you to use the <code>tasty-travis</code> template. It will include the boilerplate for:</p>
<ul>
<li>tests</li>
<li>doctest</li>
<li>benchmark</li>
<li>travis CI</li>
<li>a README file to help you start</li>
</ul>
<p>So edit your <code>~/.stack/config.yaml</code> like this:</p>
<pre><code>templates:
params:
author-name: Your Name
author-email: your@mail.com
copyright: &#39;Copyright: (c) 2016 Your Name&#39;
github-username: yourusername
category: Development</code></pre>
<p>And then you can create a new projec with:</p>
<pre><code>stack new my-project tasty-travis</code></pre>
<h2 id="generated-documentation">Generated Documentation</h2>
<p>Even not doing anything, if you submit your library to hackage, haddock should generate some API documentation for free.</p>
<p>But to make <em>real</em> documentation you <em>need</em> to add some manual annotations.</p>
<p><strong>Functions</strong>:</p>
<pre><code><span class="highlight">-- | My function description</span>
myFunction :: T1 <span class="highlight">-- ^ arg1 description</span>
-&gt; T2 <span class="highlight">-- ^ arg2 description</span>
myFunction arg1 arg2 = ...</code></pre>
<p><strong>Data</strong>:</p>
<pre><code>data MyData a b
= C1 a b -- ^ doc for constructor C1
| C2 a b -- ^ doc for constructor C2
data MyData a b
= C { a :: TypeA <span class="highlight">-- ^ field a description</span>
, b :: TypeB <span class="highlight">-- ^ field b description</span>
}</code></pre>
<p><strong>Module</strong>:</p>
<pre><code>{-|
Module : MyModule
Description: Short description
Copyright : (c)
License : MIT
Here is a longer description of this module.
With some code symbol @MyType@.
And also a block of code:
@
data MyData = C Int Int
myFunction :: MyData -&gt; Int
@
-}</code></pre>
<p><strong>Documentation Structure</strong>:</p>
<pre><code>module MyModule (
-- * Classes
C(..),
-- * Types
-- ** A data type
T,
-- ** A record
R,
-- * Some functions
f, g
) where</code></pre>
<p>That will generate headings.</p>
<h2 id="other-random-ideas">Other Random Ideas</h2>
<p>In Haskell we have great tools like <a href="http://hayoo.fh-wedel.de"><code>hayoo!</code></a> and <a href="https://www.haskell.org/hoogle/"><code>hoogle</code></a>.</p>
<p>And <code>hackage</code> and <code>stackage</code> provide also a lot of informations.</p>
<p>But generally we lack a lot of Tutorials and Guides. This post was an attempt to help people making more of them.</p>
<p>But there are other good ideas to help improve the situation.</p>
<h3 id="create-a-doc-with-link-to-best-practices">Create a doc with link to best practices</h3>
<p>In clojure when you create a new project using <code>lein new my-project</code> a directory <code>doc</code> is created for you. It contains a file with a link to this blog post:</p>
<ul>
<li><a href="https://jacobian.org/writing/what-to-write/">What to write</a></li>
</ul>
<h3 id="having-a-page-by-functionsymbol-with-comments">Having a page by function/symbol with comments</h3>
<p>If you try to search for some clojure function on a search engine there is a big chance the first result will link to:</p>
<ul>
<li><a href="http://clojuredocs.org"><code>clojuredocs.org</code></a>: try to search for <code>reduce</code>, <code>update-in</code> or <code>index</code> for example</li>
</ul>
<p>For each symbol necessiting a documentation. You dont only have the details and standard documentation. Youll also get:</p>
<ul>
<li>Responsive Design (sometime you want to look at documentation on a mobile)</li>
<li>Contributed Examples</li>
<li>Contributed See Also section</li>
<li>Contributed notes/comments</li>
</ul>
<p><a href="http://clojuredocs.org"><code>clojuredocs.org</code></a> is an independant website from the official Clojure website.</p>
<p>Most of the time, if you google the function you search you end up on <a href="http://clojuredocs.org">clojuredocs</a> for wich there are many contributions.</p>
<p>Currently stackage is closer to these feature than hackage. Because on stackage you have access to the README and also some comments by package.</p>
<p>I believe it would be more efficient to have at least a page by module and why not a page by <em>symbol</em> (data, functions, typeclasses…).</p>
<p>For example, we could provide details about <code>foldl</code> for example. Also as there would be less information to display, it will make the design cleaner.</p>
<p>Today, if you want to help documenting, you need to make a PR to the source of some library. While if we had an equivalent to clojuredocs for Haskell, adding documentation would simply be a few clicks away:</p>
<ol type="1">
<li>login</li>
<li>add/edit some example, comments, see-also section</li>
</ol>
<p>There are more than 23k people on <code>/r/haskell</code>. If only 1% of them would take 10 minutes adding a bit of documentation it will certainly change a lot of things in the percieved documentation quality.</p>
<p>And last but not least,</p>
<h2 id="design-is-important"><strong>Design is important</strong></h2>
<div>
<img src="/Scratch/img/blog/Haskell-Tutorials--a-tutorial/design_is_important.jpg" alt="Design is Important"/>
</div>
<p>Design is a vague word. A good design should care not only about how something look, but also how users will interact with it. For example by removing things to focus on the essential.</p>
<p>When I stumble upon some random blog post or random specification in the Haskell community, I had too much a feeling of old fashioned design.</p>
<p>If you look at node.js community lot of their web page look cleaner, easier to read and in the end, more user friendly.</p>
<p>Haskell is very different from node, I wouldnt like to replace all long and precise documentation with short human unprecise concepts. I dont want to transform scientific papers by tweets.</p>
<p>But like the scientific community has upgraded with the use of LaTeX, I believe we could find something similar that would make, very clean environment for most of us. A kind of look and feel that will be</p>
<ul>
<li>modern</li>
<li>device friendly (either on computer, mobile, tablet)</li>
<li>efficient, focus on what is most important and is helpful</li>
</ul>]]></summary>
</entry>
<entry>
<title>Vim as IDE</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Vim-as-IDE/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Vim-as-IDE/index.html</id>
<published>2014-12-07T00:00:00Z</published>
<updated>2014-12-07T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Vim-as-IDE/vim_spock.jpg" alt="Main image"/>
</div>
<div class="intro">
<p><span class="sc"><abbr title="Trop long; pas lu">tlpl</abbr>: </span> Comment utiliser vim comme une IDE très efficace</p>
<p>In <a href="/Scratch/en/blog/Learn-Vim-Progressively/">Learn Vim Progressively</a> Ive show how Vim is great for editing text, and navigating in the same file (buffer). In this short article youll see how I use Vim as an IDE. Mainly by using some great plugins.</p>
</div>
<h2 id="vim-plugin-manager">Vim Plugin Manager</h2>
<p>There are a <em>lot</em> of Vim plugins. To manage them I use <a href="https://github.com/junegunn/vim-plug"><code>vim-plug</code></a>.</p>
<p>To install it:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode zsh"><code class="sourceCode zsh"><a class="sourceLine" id="cb1-1" title="1"><span class="kw">mkdir</span> -p ~/.vim/autoload</a>
<a class="sourceLine" id="cb1-2" title="2">curl -fLo ~/.vim/autoload/plug.vim <span class="kw">\</span></a>
<a class="sourceLine" id="cb1-3" title="3"> https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim</a></code></pre></div>
<div class="small">
<p>☞ Note I have two parts in my <code>.vimrc</code>. The first part contains the list of all my plugins. The second part contains the personal preferences I setted for each plugin. Ill separate each part by <code>...</code> in the code.</p>
</div>
<h2 id="survival">Survival</h2>
<h3 id="colorscheme">Colorscheme</h3>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/solarized.png" alt="Solarized theme"/>
</div>
<p>Before anything, you should protect your eyes using a readable and low contrast colorscheme.</p>
<p>For this I use <a href="http://ethanschoonover.com/solarized">solarized dark</a>. To add it, you only have to write this in your <code>~/.vimrc</code> file:</p>
<pre class="vim"><code>call plug#begin(&#39;~/.vim/plugged&#39;)
Plug &#39;altercation/vim-colors-solarized&#39;
call plug#end()
&quot; -- solarized personal conf
set background=dark
try
colorscheme solarized
catch
endtry</code></pre>
<h3 id="minimal-hygiene">Minimal hygiene</h3>
<p>You should be able to see and destroy trailing whitespaces.</p>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/trim.gif" alt="Trim whitespaces"/>
</div>
<pre class="vim"><code>Plug &#39;bronson/vim-trailing-whitespace&#39;</code></pre>
<p>You can clean trailing whitespace with <code>:FixWhitespace</code>.</p>
<p>And also you should see your 80th column.</p>
<pre class="vim"><code>if (exists(&#39;+colorcolumn&#39;))
set colorcolumn=80
highlight ColorColumn ctermbg=9
endif</code></pre>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/80thcolumn.png" alt="80th column"/>
</div>
<h2 id="file-management">File Management</h2>
<p>One of the most important hidden skills in programming is the ability to search and find files in your projects.</p>
<p>The majority of people use something like <code>NERDTree</code>. This is the classical left column with a tree of files of your project. <em>I stopped to use this</em>. And you should probably too.</p>
<p>I switched to <em>unite</em>. No left column lost. Faster to find files. Mainly it works like Spotlight on OS X.</p>
<p>First install <a href="https://github.com/ggreer/the_silver_searcher"><code>ag</code> (the silver search)</a>. If you dont know <code>ack</code> or <code>ag</code> your life is going to be upgraded. This is a simple but essential tool. It is mostly a <code>grep</code> on steroids.</p>
<pre class="vim"><code>&quot; Unite
&quot; depend on vimproc
&quot; ------------- VERY IMPORTANT ------------
&quot; you have to go to .vim/plugin/vimproc.vim and do a ./make
&quot; -----------------------------------------
Plug &#39;Shougo/vimproc.vim&#39;
Plug &#39;Shougo/unite.vim&#39;
...
let g:unite_source_history_yank_enable = 1
try
let g:unite_source_rec_async_command=&#39;ag --nocolor --nogroup -g &quot;&quot;&#39;
call unite#filters#matcher_default#use([&#39;matcher_fuzzy&#39;])
catch
endtry
&quot; search a file in the filetree
nnoremap &lt;space&gt;&lt;space&gt; :split&lt;cr&gt; :&lt;C-u&gt;Unite -start-insert file_rec/async&lt;cr&gt;
&quot; reset not it is &lt;C-l&gt; normally
:nnoremap &lt;space&gt;r &lt;Plug&gt;(unite_restart)</code></pre>
<p>Now type space twice. A list of files appears. Start to type some letters of the file you are searching for. Select it, type return and bingo the file opens in a new horizontal split.</p>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/unite.gif" alt="Unite example"/>
</div>
<p>If something goes wrong just type <code>&lt;space&gt;r</code> to reset the unite cache.</p>
<p>Now you are able to search file by name easily and efficiently.</p>
<p>Now search text in many files. For this you use <a href="https://github.com/ggreer/the_silver_searcher"><code>ag</code></a>:</p>
<pre class="vim"><code>Plug &#39;rking/ag.vim&#39;
...
&quot; --- type ° to search the word in all files in the current dir
nmap ° :Ag &lt;c-r&gt;=expand(&quot;&lt;cword&gt;&quot;)&lt;cr&gt;&lt;cr&gt;
nnoremap &lt;space&gt;/ :Ag</code></pre>
<p>Dont forget to add a space after the <code>:Ag</code>.</p>
<p>These are two of the most powerful shortcut for working in a project. using <code>°</code> which is nicely positioned on my <code>azerty</code> keyboard. You should use a key close to <code>*</code>.</p>
<p>So what <code>°</code> is doing? It reads the string under the cursor and search for it in all files. Really useful to search where a function is used.</p>
<p>If you type <code>&lt;space&gt;/</code> followed by a string, it will search for all occurrences of this string in the project files.</p>
<p>So with this you should already be able to navigate between files very easily.</p>
<h2 id="language-agnostic-plugins">Language Agnostic Plugins</h2>
<h3 id="git">Git</h3>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/git-gutter.png" alt="Show modified lines"/>
</div>
<p>Show which line changed since your last commit.</p>
<pre class="vim"><code>Plug &#39;airblade/vim-gitgutter&#39;</code></pre>
<p>And the “defacto” git plugin:</p>
<pre class="vim"><code>Plug &#39;tpope/vim-fugitive&#39;</code></pre>
<p>You can reset your changes from the latest git commit with <code>:Gread</code>. You can stage your changes with <code>:Gwrite</code>.</p>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/Gread.gif" alt="Reset changes"/>
</div>
<h3 id="align-things">Align things</h3>
<pre class="vim"><code>Plug &#39;junegunn/vim-easy-align&#39;
...
&quot; Easy align interactive
vnoremap &lt;silent&gt; &lt;Enter&gt; :EasyAlign&lt;cr&gt;</code></pre>
<p>Just select and type <code>Return</code> then <code>space</code>. Type <code>Return</code> many type to change the alignments.</p>
<p>If you want to align the second column, <code>Return</code> then <code>2</code> then <code>space</code>.</p>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/easy-align.gif" alt="Easy align example"/>
</div>
<h3 id="basic-auto-completion-c-n-c-p">Basic auto completion: <code>C-n</code> &amp; <code>C-p</code></h3>
<p>Vim has a basic auto completion system. The shortcuts are <code>C-n</code> and <code>C-p</code> while you are in insert mode. This is generally good enough in most cases. For example when I open a file not in my configured languages.</p>
<h2 id="haskell">Haskell</h2>
<p>My current Haskell programming environment is great!</p>
<p>Each time I save a file, I get a comment pointing to my errors or proposing me how to improve my code.</p>
<p>So here we go:</p>
<blockquote>
<p>☞ Dont forget to install <code>ghc-mod</code> with: <code>cabal install ghc-mod</code></p>
</blockquote>
<pre class="vim"><code>&quot; ---------- VERY IMPORTANT -----------
&quot; Don&#39;t forget to install ghc-mod with:
&quot; cabal install ghc-mod
&quot; -------------------------------------
Plug &#39;scrooloose/syntastic&#39; &quot; syntax checker
&quot; --- Haskell
Plug &#39;yogsototh/haskell-vim&#39; &quot; syntax indentation / highlight
Plug &#39;enomsg/vim-haskellConcealPlus&#39; &quot; unicode for haskell operators
Plug &#39;eagletmt/ghcmod-vim&#39;
Plug &#39;eagletmt/neco-ghc&#39;
Plug &#39;Twinside/vim-hoogle&#39;
Plug &#39;pbrisbin/html-template-syntax&#39; &quot; Yesod templates
...
&quot; -------------------
&quot; Haskell
&quot; -------------------
let mapleader=&quot;-&quot;
let g:mapleader=&quot;-&quot;
set tm=2000
nmap &lt;silent&gt; &lt;leader&gt;ht :GhcModType&lt;CR&gt;
nmap &lt;silent&gt; &lt;leader&gt;hh :GhcModTypeClear&lt;CR&gt;
nmap &lt;silent&gt; &lt;leader&gt;hT :GhcModTypeInsert&lt;CR&gt;
nmap &lt;silent&gt; &lt;leader&gt;hc :SyntasticCheck ghc_mod&lt;CR&gt;:lopen&lt;CR&gt;
let g:syntastic_mode_map={&#39;mode&#39;: &#39;active&#39;, &#39;passive_filetypes&#39;: [&#39;haskell&#39;]}
let g:syntastic_always_populate_loc_list = 1
nmap &lt;silent&gt; &lt;leader&gt;hl :SyntasticCheck hlint&lt;CR&gt;:lopen&lt;CR&gt;
&quot; Auto-checking on writing
autocmd BufWritePost *.hs,*.lhs GhcModCheckAndLintAsync
&quot; neocomplcache (advanced completion)
autocmd BufEnter *.hs,*.lhs let g:neocomplcache_enable_at_startup = 1
function! SetToCabalBuild()
if glob(&quot;*.cabal&quot;) != &#39;&#39;
set makeprg=cabal\ build
endif
endfunction
autocmd BufEnter *.hs,*.lhs :call SetToCabalBuild()
&quot; -- neco-ghc
let $PATH=$PATH.&#39;:&#39;.expand(&quot;~/.cabal/bin&quot;)</code></pre>
<p>Just enjoy!</p>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/vim-lint.gif" alt="hlint on save"/>
</div>
<p>I use <code>-</code> for my leader because I use <code>,</code> a lot for its native usage.</p>
<ul>
<li><code>-ht</code> will highlight and show the type of the block under the cursor.</li>
<li><code>-hT</code> will insert the type of the current block.</li>
<li><code>-hh</code> will unhighlight the selection.</li>
</ul>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/auto-typing.gif" alt="Auto typing on save"/>
</div>
<h2 id="clojure">Clojure</h2>
<div>
<img src="/Scratch/img/blog/Vim-as-IDE/clojure.gif" alt="Rainbow parenthesis"/>
</div>
<p>My main language at work is Clojure. And my current vim environment is quite good. I lack the automatic integration to <code>lein-kibit</code> thought. If I have the courage I might do it myself one day. But due to the very long startup time of clojure, I doubt Ill be able to make a useful vim plugin.</p>
<p>So mainly youll have real rainbow-parenthesis (the default values are broken for solarized).</p>
<p>I used the vim <code>paredit</code> plugin before. But it is too restrictive. Now I use <code>sexp</code> which feel more coherent with the spirit of vim.</p>
<pre class="vim"><code>&quot; &quot; -- Clojure
Plug &#39;kien/rainbow_parentheses.vim&#39;
Plug &#39;guns/vim-clojure-static&#39;
Plug &#39;guns/vim-sexp&#39;
Plug &#39;tpope/vim-repeat&#39;
Plug &#39;tpope/vim-fireplace&#39;
...
autocmd BufEnter *.cljs,*.clj,*.cljs.hl RainbowParenthesesActivate
autocmd BufEnter *.cljs,*.clj,*.cljs.hl RainbowParenthesesLoadRound
autocmd BufEnter *.cljs,*.clj,*.cljs.hl RainbowParenthesesLoadSquare
autocmd BufEnter *.cljs,*.clj,*.cljs.hl RainbowParenthesesLoadBraces
autocmd BufEnter *.cljs,*.clj,*.cljs.hl setlocal iskeyword+=?,-,*,!,+,/,=,&lt;,&gt;,.,:
&quot; -- Rainbow parenthesis options
let g:rbpt_colorpairs = [
\ [&#39;darkyellow&#39;, &#39;RoyalBlue3&#39;],
\ [&#39;darkgreen&#39;, &#39;SeaGreen3&#39;],
\ [&#39;darkcyan&#39;, &#39;DarkOrchid3&#39;],
\ [&#39;Darkblue&#39;, &#39;firebrick3&#39;],
\ [&#39;DarkMagenta&#39;, &#39;RoyalBlue3&#39;],
\ [&#39;darkred&#39;, &#39;SeaGreen3&#39;],
\ [&#39;darkyellow&#39;, &#39;DarkOrchid3&#39;],
\ [&#39;darkgreen&#39;, &#39;firebrick3&#39;],
\ [&#39;darkcyan&#39;, &#39;RoyalBlue3&#39;],
\ [&#39;Darkblue&#39;, &#39;SeaGreen3&#39;],
\ [&#39;DarkMagenta&#39;, &#39;DarkOrchid3&#39;],
\ [&#39;Darkblue&#39;, &#39;firebrick3&#39;],
\ [&#39;darkcyan&#39;, &#39;SeaGreen3&#39;],
\ [&#39;darkgreen&#39;, &#39;RoyalBlue3&#39;],
\ [&#39;darkyellow&#39;, &#39;DarkOrchid3&#39;],
\ [&#39;darkred&#39;, &#39;firebrick3&#39;],
\ ]</code></pre>
<p>Working with Clojure will becomre quite smoother. You can eval any part of your code, you must launch a Clojure REPL manually in another terminal thought.</p>
<h2 id="last-words">Last words</h2>
<p>I hope it will be useful.</p>
<p>Last but not least, if you want to use my vim configuration you can get it here:</p>
<p><a href="http://github.com/yogsototh/vimrc"><code>github.com/yogsototh/vimrc</code></a></p>]]></summary>
</entry>
<entry>
<title>Installer Haskell</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Safer-Haskell-Install/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Safer-Haskell-Install/index.html</id>
<published>2014-08-16T00:00:00Z</published>
<updated>2014-08-16T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Safer-Haskell-Install/main.jpg" alt="to Haskell and Beyond!!!"/>
</div>
<div class="intro">
<p><span class="sc"><abbr title="Trop long; pas lu">tlpl</abbr>: </span> Pour installer Haskell (OS X et Linux) copiez/collez les lignes suivante dans un terminal&nbsp;:</p>
<pre><code>curl https://raw.githubusercontent.com/yogsototh/install-haskell/master/install-haskell.sh | sudo zsh</code></pre>
<p>Si vous êtes sous windows, téléchargez Haskell Platform et suivez les instructions pour utiliser <a href="http://www.stackage.org/lts">Haskell LTS</a>.</p>
<p>Si vous voulez savoir le pourquoi et le comment ; lisez le reste de larticle.</p>
</div>
<h2 id="pourquoi">Pourquoi ?</h2>
<p>La plus grande faiblesse dHaskell na rien à voir avec le langage en lui-même mais avec son écosystème.</p>
<p>The main problem Ill try to address is the one known as <em>cabal hell</em>. The community is really active in fixing the issue. I am very confident that in less than a year this problem will be one of the past. But to work today, I provide an install method that should reduce greatly two effects of cabal hell:</p>
<ul>
<li>dependency error</li>
<li>lost time in compilation (poor polar bears)</li>
</ul>
<p>With my actual installation method, you should minimize your headache and almost never hit a dependency error. But there could exists some. If you encounter any dependency error, ask gently to the package manager to port its package to <a href="http://www.stackage.org">stackage</a>.</p>
<p>So to install copy/paste the following three lines in your terminal:</p>
<pre><code>curl https://raw.githubusercontent.com/yogsototh/install-haskell/master/install-haskell.sh | sudo zsh</code></pre>
<h2 id="how">How?</h2>
<p>You can read the script and you will see that this is quite straightforward.</p>
<ol type="1">
<li>It downloads the latest <code>GHC</code> binary for you system and install it.</li>
<li>It does the same with the <code>cabal</code> program.</li>
<li>It updates your cabal config file to use <a href="http://www.stackage.org/lts">Haskell LTS</a>.</li>
<li>It enable profiling to libraries and executables.</li>
<li>It installs some useful binaries that might cause compilation error if not present.</li>
</ol>
<p>As the version of libraries is fixed up until you update the <a href="http://www.stackage.org/lts">Haskell LTS</a> version, you should never use cabal sandbox. That way, you will only compile each needed library once. The compiled objects/binaries will be in your <code>~/.cabal</code> directory.</p>
<h2 id="some-last-words">Some Last Words</h2>
<p>This script use the latest <a href="http://www.stackage.org/lts">Haskell LTS</a>. So if you use this script at different dates, the Haskell LTS might have changed.</p>
<p>While it comes to cabal hell, some solutions are sandboxes and <code>nix</code>. Unfortunately, sandboxes didnt worked good enough for me after some time. Furthermore, sandboxes forces you to re-compile everything by project. If you have three yesod projects for example it means a lot of time and CPU. Also, <code>nix</code> didnt worked as expected on OS X. So fixing the list of package to a stable list of them seems to me the best pragmatic way to handle the problem today.</p>
<p>From my point of view, <a href="http://www.stackage.org/lts">Haskell LTS</a> is the best step in the right direction. The actual cabal hell problem is more a human problem than a tool problem. This is a bias in most programmer to prefer resolve social issues using tools. There is nothing wrong with hackage and cabal. But for a package manager to work in a static typing language as Haskell, packages must work all together. This is a great strength of static typed languages that they ensure that a big part of the API between packages are compatible. But this make the job of package managing far more difficult than in dynamic languages.</p>
<p>People tend not to respect the rules in package numbering<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a>. They break their API all the time. So we need a way to organize all of that. And this is precisely what <a href="http://www.stackage.org/lts">Haskell LTS</a> provide. A set of stable packages working all together. So if a developer break its API, it wont work anymore in stackage. And whether the developer fix its package or all other packages upgrade their usage. During this time, <a href="http://www.stackage.org/lts">Haskell LTS</a> end-users will be able to develop without dependency issues.</p>
<hr />
<p class="small">
<a href="https://www.flickr.com/photos/nesster/4198442186/">The image of the cat about to jump that I slightly edited can found here</a>
</p>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>I myself am guilty of such behavior. It was a beginner error.<a href="#fnref1" class="footnote-back">↩</a></p></li>
</ol>
</section>]]></summary>
</entry>
<entry>
<title>Sacré Haskell Projet</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Holy-Haskell-Starter/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Holy-Haskell-Starter/index.html</id>
<published>2013-11-14T00:00:00Z</published>
<updated>2013-11-14T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/holy-grail-monty-python.jpg" alt="Monty Python Holy Grail"/>
</div>
<div class="intro">
<p><span class="sc"><abbr title="Trop long; pas lu">tlpl</abbr>: </span> Apprenez comment commencer un nouveau projet Haskell. Avec en exemple le créateur de projet Haskell lui-même.</p>
<blockquote>
<p>“Good Sir Knight, will you come with me to Camelot, and join us at the Round Table?”</p>
</blockquote>
<p>In order to work properly with Haskell you need to initialize your environment. Typically, you need to use a cabal file, create some test for your code. Both, unit test and propositional testing (random and exhaustive up to a certain depth). You need to use <code>git</code> and generally hosting it on github. Also, it is recommended to use cabal sandboxes. And as bonus, an auto-update tool that recompile and retest on each file save.</p>
<p>In this article, we will create such an environment using a zsh script. Then we will write a Haskell project which does the same work as the zsh script. You will then see how to work in such an environment.</p>
<p>If you are starting to understand Haskell but consider yourself a beginner, this tutorial will show you how to make a real application using quite surprisingly a lot of features:</p>
<ul>
<li>use colorized output</li>
<li>interact with a user in command line</li>
<li>read/write files</li>
<li>kind of parse a file (in fact, simply split it)</li>
<li>use a templating system (mustache: fill a data structure, write files)</li>
<li>make a HTTP GET request then parse the JSON answer and use it</li>
<li>use random</li>
<li>create a cabal package</li>
<li>add and use non source files to a cabal package</li>
<li>Test your code (both unit testing and property testing)</li>
</ul>
<p><strong>☞</strong> zsh is by its nature more suitable to file manipulation. But the Haskell code is clearly more organized while quite terse for a multi-purpose language.</p>
<p><strong>☞</strong> holy-project is on hackage. It can be installed with <code>cabal update &amp;&amp; cabal install holy-project</code>.</p>
</div>
<p>I recently read this excellent article: <a href="http://jabberwocky.eu/2013/10/24/how-to-start-a-new-haskell-project/">How to Start a New Haskell Project</a>.</p>
<p>While the article is very good, I lacked some minor informations<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a>. Inspired by it, I created a simple script to initialize a new Haskell project. During the process I improved some things a bit.</p>
<p>If you want to use this script, the steps are:</p>
<ol type="1">
<li><a href="http://wwW.haskell.org/platform">Install Haskell</a></li>
<li>Make sure you have the latest <code>cabal-install</code> (at least 1.18)</li>
</ol>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb1-1" title="1"><span class="op">&gt;</span> <span class="ex">cabal</span> install cabal-install</a></code></pre></div>
<ol start="3" type="1">
<li>Download and run the script</li>
</ol>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" title="1"><span class="co"># Download the script</span></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="fu">git</span> clone https://github.com/yogsototh/init-haskell-project.git</a>
<a class="sourceLine" id="cb2-3" title="3"><span class="co"># Copy the script in a directory of you PATH variable</span></a>
<a class="sourceLine" id="cb2-4" title="4"><span class="fu">cp</span> init-haskell-project/holy-haskell.sh ~/bin</a>
<a class="sourceLine" id="cb2-5" title="5"><span class="co"># Go to the directory containing all your projects</span></a>
<a class="sourceLine" id="cb2-6" title="6"><span class="bu">cd</span> my/projects/directory</a>
<a class="sourceLine" id="cb2-7" title="7"><span class="co"># Launch thcript</span></a>
<a class="sourceLine" id="cb2-8" title="8"><span class="ex">holy-haskell.sh</span></a></code></pre></div>
<p>What does this script do that <code>cabal init</code> doesnt do?</p>
<ul>
<li>Use cabal sandbox</li>
<li>It initialize <code>git</code> with the right <code>.gitignore</code> file.</li>
<li>Use <code>tasty</code> to organize your tests (HUnit, QuickCheck and SmallCheck).</li>
<li>Use <code>-Wall</code> for <code>ghc</code> compilation.</li>
<li>Will make references to Holy Grail</li>
<li>Search your default github username via <a href="http://developer.github.com/v3/search/#search-users">github api</a>.</li>
</ul>
<h2 id="zsh-really"><code>zsh</code> really?</h2>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/french-insult.jpg" alt="French insult"/>
</div>
<p>Developing the script in <code>zsh</code> was easy. But considering its size, it is worth to rewrite it in Haskell. Furthermore, it will be a good exercise.</p>
<h3 id="patricide">Patricide</h3>
<p>In a first time, we initialize a new Haskell project with <code>holy-haskell.sh</code>:</p>
<pre>
> ./holy-haskell.sh
<span class="green">Bridgekeeper: Stop!
Bridgekeeper: Who would cross the Bridge of Death
Bridgekeeper: must answer me these questions three,
Bridgekeeper: ere the other side he see.</span>
<span class="yellow">You: Ask me the questions, bridgekeeper, I am not afraid.</span>
<span class="green">Bridgekeeper: What is the name of your project?</span>
> Holy project
<span class="green">Bridgekeeper: What is your name?</span> (Yann Esposito (Yogsototh))
>
<span class="green">Bridgekeeper: What is your email?</span> (Yann.Esposito@gmail.com)
>
<span class="green">Bridgekeeper: What is your github user name?</span> (yogsototh)
>
<span class="green">Bridgekeeper: What is your project in less than ten words?</span>
> Start your Haskell project with cabal, git and tests.
Initialize git
Initialized empty Git repository in .../holy-project/.git/
Create files
.gitignore
holy-project.cabal
Setup.hs
LICENSE (MIT)
test/Test.hs
test/HolyProject/Swallow/Test.hs
src/HolyProject/Swallow.hs
test/HolyProject/Coconut/Test.hs
src/HolyProject/Coconut.hs
src/HolyProject.hs
src/Main.hs
Cabal sandboxing, install and test
...
many compilations lines
...
Running 1 test suites...
Test suite Tests: RUNNING...
Test suite Tests: PASS
Test suite logged to: dist/test/holy-project-0.1.0.0-Tests.log
1 of 1 test suites (1 of 1 test cases) passed.
All Tests
Swallow
swallow test: <span class="green">OK</span>
coconut
coconut: <span class="green">OK</span>
coconut property: <span class="green">OK</span>
148 tests completed
<span class="green">All 3 tests passed</span>
<span class="green">Bridgekeeper: What... is the air-speed velocity of an unladen swallow?</span>
<span class="yellow">You: What do you mean? An African or European swallow?</span>
<span class="green">Bridgekeeper: Huh? I... I don't know that.</span>
[the bridgekeeper is thrown over]
<span class="green">Bridgekeeper: Auuuuuuuuuuuugh</span>
Sir Bedevere: How do you know so much about swallows?
<span class="yellow">You: Well, you have to know these things when you're a king, you know.</span>
</pre>
<p>The different steps are:</p>
<ul>
<li>small introduction quotes</li>
<li>ask five questions <em>three question sir…</em></li>
<li>create the directory for the project</li>
<li>init git</li>
<li>create files</li>
<li>sandbox cabal</li>
<li>cabal install and test</li>
<li>run the test directly in the terminal</li>
<li>small goodbye quotes</li>
</ul>
<p>Features to note:</p>
<ul>
<li>color in the terminal</li>
<li>check some rules on the project name</li>
<li>random message if error</li>
<li>use <code>~/.gitconfig</code> file in order to provide a default name and email.</li>
<li>use the github API which returns JSON to get the default github user name.</li>
</ul>
<p>So, apparently nothing too difficult to achieve.</p>
<p>We should now have an initialized Haskell environment for us to work. The first thing you should do, is to go into this new directory and launch ./auto-update in some terminal. I personally use <code>tmux</code> on Linux or the splits in <code>iTerm 2</code> on Mac OS X. Now, any modification of a source file will relaunch a compilation and a test.</p>
<h3 id="the-dialogs">The dialogs</h3>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/bridge-of-death.jpg" alt="Bridge of Death"/>
</div>
<p>To print the introduction text in <code>zsh</code>:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb3-1" title="1"><span class="co"># init colors</span></a>
<a class="sourceLine" id="cb3-2" title="2"><span class="ex">autoload</span> colors</a>
<a class="sourceLine" id="cb3-3" title="3"><span class="ex">colors</span></a>
<a class="sourceLine" id="cb3-4" title="4"><span class="kw">for</span> <span class="ex">COLOR</span> in RED GREEN YELLOW BLUE MAGENTA CYAN BLACK WHITE<span class="kw">;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb3-5" title="5"> <span class="bu">eval</span> <span class="va">$COLOR</span>=<span class="st">&#39;$fg_no_bold[${(L)COLOR}]&#39;</span></a>
<a class="sourceLine" id="cb3-6" title="6"> <span class="bu">eval</span> BOLD_<span class="va">$COLOR</span>=<span class="st">&#39;$fg_bold[${(L)COLOR}]&#39;</span></a>
<a class="sourceLine" id="cb3-7" title="7"><span class="kw">done</span></a>
<a class="sourceLine" id="cb3-8" title="8"><span class="bu">eval</span> RESET=<span class="st">&#39;$reset_color&#39;</span></a>
<a class="sourceLine" id="cb3-9" title="9"><span class="co"># functions</span></a>
<a class="sourceLine" id="cb3-10" title="10"><span class="fu">bk()</span>{<span class="ex">print</span> -- <span class="st">&quot;</span><span class="va">${GREEN}</span><span class="st">Bridgekeeper: </span><span class="va">$*${RESET}</span><span class="st">&quot;</span>}</a>
<a class="sourceLine" id="cb3-11" title="11"><span class="fu">bkn()</span>{<span class="ex">print</span> -n -- <span class="st">&quot;</span><span class="va">${GREEN}</span><span class="st">Bridgekeeper: </span><span class="va">$*${RESET}</span><span class="st">&quot;</span>}</a>
<a class="sourceLine" id="cb3-12" title="12"><span class="fu">you()</span>{<span class="ex">print</span> -- <span class="st">&quot;</span><span class="va">${YELLOW}</span><span class="st">You: </span><span class="va">$*${RESET}</span><span class="st">&quot;</span>}</a>
<a class="sourceLine" id="cb3-13" title="13"><span class="ex">...</span></a>
<a class="sourceLine" id="cb3-14" title="14"><span class="co"># the introduction dialog</span></a>
<a class="sourceLine" id="cb3-15" title="15"><span class="ex">bk</span> <span class="st">&quot;Stop!&quot;</span></a>
<a class="sourceLine" id="cb3-16" title="16"><span class="ex">bk</span> <span class="st">&quot;Who would cross the Bridge of Death&quot;</span></a>
<a class="sourceLine" id="cb3-17" title="17"><span class="ex">bk</span> <span class="st">&quot;must answer me these questions three,&quot;</span></a>
<a class="sourceLine" id="cb3-18" title="18"><span class="ex">bk</span> <span class="st">&quot;ere the other side he see.&quot;</span></a>
<a class="sourceLine" id="cb3-19" title="19"><span class="ex">you</span> <span class="st">&quot;Ask me the questions, bridgekeeper, I am not afraid.\n&quot;</span></a>
<a class="sourceLine" id="cb3-20" title="20"><span class="ex">...</span></a>
<a class="sourceLine" id="cb3-21" title="21"><span class="co"># the final dialog</span></a>
<a class="sourceLine" id="cb3-22" title="22"><span class="ex">print</span> <span class="st">&quot;\n\n&quot;</span></a>
<a class="sourceLine" id="cb3-23" title="23"><span class="ex">bk</span> <span class="st">&quot;What... is the air-speed velocity of an unladen swallow?&quot;</span></a>
<a class="sourceLine" id="cb3-24" title="24"><span class="ex">you</span> <span class="st">&quot;What do you mean? An African or European swallow?&quot;</span></a>
<a class="sourceLine" id="cb3-25" title="25"><span class="ex">bk</span> <span class="st">&quot;Huh? I... I don&#39;t know that.&quot;</span></a>
<a class="sourceLine" id="cb3-26" title="26"><span class="ex">log</span> <span class="st">&quot;[the bridgekeeper is thrown over]&quot;</span></a>
<a class="sourceLine" id="cb3-27" title="27"><span class="ex">bk</span> <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb3-28" title="28"><span class="ex">log</span> <span class="st">&quot;Sir Bedevere: How do you know so much about swallows?&quot;</span></a>
<a class="sourceLine" id="cb3-29" title="29"><span class="ex">you</span> <span class="st">&quot;Well, you have to know these things when you&#39;re a king, you know.&quot;</span></a></code></pre></div>
<p>In the first Haskell version I dont use colors. We see we can almost copy/paste. I just added the types.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb4-1" title="1"><span class="ot">bk ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-2" title="2">bk str <span class="ot">=</span> <span class="fu">putStrLn</span> <span class="op">$</span> <span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str</a>
<a class="sourceLine" id="cb4-3" title="3"></a>
<a class="sourceLine" id="cb4-4" title="4"><span class="ot">bkn ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-5" title="5">bkn str <span class="ot">=</span> pustStr <span class="op">$</span> <span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str</a>
<a class="sourceLine" id="cb4-6" title="6"></a>
<a class="sourceLine" id="cb4-7" title="7"><span class="ot">you ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-8" title="8">you str <span class="ot">=</span> <span class="fu">putStrLn</span> <span class="op">$</span> <span class="st">&quot;You: &quot;</span> <span class="op">++</span> str</a>
<a class="sourceLine" id="cb4-9" title="9"></a>
<a class="sourceLine" id="cb4-10" title="10"><span class="ot">intro ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-11" title="11">intro <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb4-12" title="12"> bk <span class="st">&quot;Stop!&quot;</span></a>
<a class="sourceLine" id="cb4-13" title="13"> bk <span class="st">&quot;Who would cross the Bridge of Death&quot;</span></a>
<a class="sourceLine" id="cb4-14" title="14"> bk <span class="st">&quot;must answer me these questions three,&quot;</span></a>
<a class="sourceLine" id="cb4-15" title="15"> bk <span class="st">&quot;ere the other side he see.&quot;</span></a>
<a class="sourceLine" id="cb4-16" title="16"> you <span class="st">&quot;Ask me the questions, bridgekeeper, I am not afraid.\n&quot;</span></a>
<a class="sourceLine" id="cb4-17" title="17"></a>
<a class="sourceLine" id="cb4-18" title="18"><span class="ot">end ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-19" title="19">end <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb4-20" title="20"> <span class="fu">putStrLn</span> <span class="st">&quot;\n\n&quot;</span></a>
<a class="sourceLine" id="cb4-21" title="21"> bk <span class="st">&quot;What... is the air-speed velocity of an unladen swallow?&quot;</span></a>
<a class="sourceLine" id="cb4-22" title="22"> you <span class="st">&quot;What do you mean? An African or European swallow?&quot;</span></a>
<a class="sourceLine" id="cb4-23" title="23"> bk <span class="st">&quot;Huh? I... I don&#39;t know that.&quot;</span></a>
<a class="sourceLine" id="cb4-24" title="24"> <span class="fu">putStrLn</span> <span class="st">&quot;[the bridgekeeper is thrown over]&quot;</span></a>
<a class="sourceLine" id="cb4-25" title="25"> bk <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb4-26" title="26"> <span class="fu">putStrLn</span> <span class="st">&quot;Sir Bedevere: How do you know so much about swallows?&quot;</span></a>
<a class="sourceLine" id="cb4-27" title="27"> you <span class="st">&quot;Well, you have to know these things when you&#39;re a king, you know.&quot;</span></a></code></pre></div>
<p>Now lets just add the colors using the <a href="http://hackage.haskell.org/package/ansi-terminal"><code>ansi-terminal</code></a> package. So we have to add <code>ansi-terminal</code> as a build dependency in our cabal file.</p>
<p>Edit <code>holy-project.cabal</code> to add it.</p>
<pre><code>...
build-depends: base &gt;=4.6 &amp;&amp; &lt;4.7
<span class="highlight">, ansi-terminal</span>
...</code></pre>
<p>Now look at the modified Haskell code:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb6-1" title="1"><span class="highlight"><span class="kw">import</span> <span class="dt">System.Console.ANSI</span></span></a>
<a class="sourceLine" id="cb6-2" title="2"></a>
<a class="sourceLine" id="cb6-3" title="3"><span class="ot">colorPutStr ::</span> <span class="dt">Color</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-4" title="4">colorPutStr color str <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb6-5" title="5"> setSGR [ <span class="dt">SetColor</span> <span class="dt">Foreground</span> <span class="dt">Dull</span> color</a>
<a class="sourceLine" id="cb6-6" title="6"> , <span class="dt">SetConsoleIntensity</span> <span class="dt">NormalIntensity</span></a>
<a class="sourceLine" id="cb6-7" title="7"> ]</a>
<a class="sourceLine" id="cb6-8" title="8"> <span class="fu">putStr</span> str</a>
<a class="sourceLine" id="cb6-9" title="9"> setSGR []</a>
<a class="sourceLine" id="cb6-10" title="10"></a>
<a class="sourceLine" id="cb6-11" title="11"></a>
<a class="sourceLine" id="cb6-12" title="12"><span class="ot">bk ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-13" title="13">bk str <span class="ot">=</span> <span class="highlight">colorPutStr <span class="dt">Green</span></span> (<span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str <span class="op">++</span> <span class="st">&quot;\n&quot;</span>)</a>
<a class="sourceLine" id="cb6-14" title="14"><span class="ot">bkn ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-15" title="15">bkn str <span class="ot">=</span> <span class="highlight">colorPutStr <span class="dt">Green</span></span> (<span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str)</a>
<a class="sourceLine" id="cb6-16" title="16"><span class="ot">you ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-17" title="17">you str <span class="ot">=</span> <span class="highlight">colorPutStr <span class="dt">Yellow</span></span> (<span class="st">&quot;You: &quot;</span> <span class="op">++</span> str <span class="op">++</span> <span class="st">&quot;\n&quot;</span>)</a>
<a class="sourceLine" id="cb6-18" title="18"></a>
<a class="sourceLine" id="cb6-19" title="19"><span class="ot">intro ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-20" title="20">intro <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb6-21" title="21"> bk <span class="st">&quot;Stop!&quot;</span></a>
<a class="sourceLine" id="cb6-22" title="22"> bk <span class="st">&quot;Who would cross the Bridge of Death&quot;</span></a>
<a class="sourceLine" id="cb6-23" title="23"> bk <span class="st">&quot;must answer me these questions three,&quot;</span></a>
<a class="sourceLine" id="cb6-24" title="24"> bk <span class="st">&quot;ere the other side he see.&quot;</span></a>
<a class="sourceLine" id="cb6-25" title="25"> you <span class="st">&quot;Ask me the questions, bridgekeeper, I am not afraid.\n&quot;</span></a>
<a class="sourceLine" id="cb6-26" title="26"></a>
<a class="sourceLine" id="cb6-27" title="27"><span class="ot">end ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-28" title="28">end <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb6-29" title="29"> <span class="fu">putStrLn</span> <span class="st">&quot;\n\n&quot;</span></a>
<a class="sourceLine" id="cb6-30" title="30"> bk <span class="st">&quot;What... is the air-speed velocity of an unladen swallow?&quot;</span></a>
<a class="sourceLine" id="cb6-31" title="31"> you <span class="st">&quot;What do you mean? An African or European swallow?&quot;</span></a>
<a class="sourceLine" id="cb6-32" title="32"> bk <span class="st">&quot;Huh? I... I don&#39;t know that.&quot;</span></a>
<a class="sourceLine" id="cb6-33" title="33"> <span class="fu">putStrLn</span> <span class="st">&quot;[the bridgekeeper is thrown over]&quot;</span></a>
<a class="sourceLine" id="cb6-34" title="34"> bk <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb6-35" title="35"> <span class="fu">putStrLn</span> <span class="st">&quot;Sir Bedevere: How do you know so much about swallows?&quot;</span></a>
<a class="sourceLine" id="cb6-36" title="36"> you <span class="st">&quot;Well, you have to know these things when you&#39;re a king, you know.&quot;</span></a></code></pre></div>
<p>We could put this code in <code>src/Main.hs</code>. Declare a main function:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb7-1" title="1"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb7-2" title="2">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb7-3" title="3"> intro</a>
<a class="sourceLine" id="cb7-4" title="4"> end</a></code></pre></div>
<p>Make <code>cabal install</code> and run <code>cabal run</code> (or <code>./.cabal-sandbox/bin/holy-project</code>). It works!</p>
<h2 id="five-questions-three-questions-sir">Five Questions Three questions Sir!</h2>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/bring-out-your-dead.jpg" alt="Bring out your dead!"/>
</div>
<p>In order to ask questions, here is how we do it in shell script:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb8-1" title="1"><span class="ex">print</span> -- <span class="st">&quot;What is your name?&quot;</span></a>
<a class="sourceLine" id="cb8-2" title="2"><span class="bu">read</span> <span class="va">name</span></a></code></pre></div>
<p>If we want to abstract things a bit, the easiest way in shell is to use a global variable<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a> which will get the value of the user input like this:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb9-1" title="1"><span class="va">answer=</span><span class="st">&quot;&quot;</span></a>
<a class="sourceLine" id="cb9-2" title="2"><span class="fu">ask()</span><span class="kw">{</span></a>
<a class="sourceLine" id="cb9-3" title="3"> <span class="bu">local</span> <span class="va">info=</span><span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span></a>
<a class="sourceLine" id="cb9-4" title="4"> <span class="ex">bk</span> <span class="st">&quot;What is your </span><span class="va">$info</span><span class="st">?&quot;</span></a>
<a class="sourceLine" id="cb9-5" title="5"> <span class="ex">print</span> -n <span class="st">&quot;&gt; &quot;</span></a>
<a class="sourceLine" id="cb9-6" title="6"> <span class="bu">read</span> <span class="va">answer</span></a>
<a class="sourceLine" id="cb9-7" title="7"><span class="kw">}</span></a>
<a class="sourceLine" id="cb9-8" title="8"><span class="ex">...</span></a>
<a class="sourceLine" id="cb9-9" title="9"><span class="ex">ask</span> name</a>
<a class="sourceLine" id="cb9-10" title="10"><span class="va">name=</span><span class="st">&quot;</span><span class="va">$answer</span><span class="st">&quot;</span></a></code></pre></div>
<p>In Haskell we wont need any global variable:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb10-1" title="1"><span class="kw">import</span> <span class="dt">System.IO</span> (hFlush, stdout)</a>
<a class="sourceLine" id="cb10-2" title="2"><span class="op">...</span></a>
<a class="sourceLine" id="cb10-3" title="3"><span class="ot">ask ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb10-4" title="4">ask info <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb10-5" title="5"> bk <span class="op">$</span> <span class="st">&quot;What is your &quot;</span> <span class="op">++</span> info <span class="op">++</span> <span class="st">&quot;?&quot;</span></a>
<a class="sourceLine" id="cb10-6" title="6"> <span class="fu">putStr</span> <span class="st">&quot;&gt; &quot;</span></a>
<a class="sourceLine" id="cb10-7" title="7"> hFlush stdout <span class="co">-- Because we want to ask on the same line.</span></a>
<a class="sourceLine" id="cb10-8" title="8"> <span class="fu">getLine</span></a></code></pre></div>
<p>Now our main function might look like:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb11-1" title="1">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb11-2" title="2"> intro</a>
<a class="sourceLine" id="cb11-3" title="3"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span></a>
<a class="sourceLine" id="cb11-4" title="4"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;name&quot;</span></a>
<a class="sourceLine" id="cb11-5" title="5"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;email&quot;</span></a>
<a class="sourceLine" id="cb11-6" title="6"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;github account&quot;</span></a>
<a class="sourceLine" id="cb11-7" title="7"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;project in less than a dozen word&quot;</span></a>
<a class="sourceLine" id="cb11-8" title="8"> end</a></code></pre></div>
<p>You could test it with <code>cabal install</code> and then <code>./.cabal-sandbox/bin/holy-project</code>.</p>
<p>We will see later how to guess the answer using the <code>.gitconfig</code> file and the github API.</p>
<h2 id="using-answers">Using answers</h2>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/castle-of-hhhhaaaarr.jpg" alt="Castle of Aaaaarrrr????"/>
</div>
<h3 id="create-the-project-name">Create the project name</h3>
<p>I dont really like the ability to use capital letter in a package name. So in shell I transform the project name like this:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb12-1" title="1"><span class="co"># replace all spaces by dashes then lowercase the string</span></a>
<a class="sourceLine" id="cb12-2" title="2"><span class="va">project=</span>${<span class="va">${project:gs</span><span class="er">/</span><span class="va"> </span><span class="er">/-/</span><span class="va">}</span>:<span class="ex">l</span>}</a></code></pre></div>
<p>In order to achieve the same result in Haskell (dont forget to add the <code>split</code> package):</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb13-1" title="1"><span class="kw">import</span> <span class="dt">Data.Char</span> (toLower)</a>
<a class="sourceLine" id="cb13-2" title="2"><span class="kw">import</span> <span class="dt">Data.List</span> (intercalate)</a>
<a class="sourceLine" id="cb13-3" title="3"><span class="kw">import</span> <span class="dt">Data.List.Split</span> (splitOneOf)</a>
<a class="sourceLine" id="cb13-4" title="4"><span class="op">...</span></a>
<a class="sourceLine" id="cb13-5" title="5"><span class="ot">projectNameFromString ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb13-6" title="6">projectNameFromString str <span class="ot">=</span> intercalate <span class="st">&quot;-&quot;</span> (splitOneOf <span class="st">&quot; -&quot;</span> (<span class="fu">map</span> <span class="fu">toLower</span> str))</a></code></pre></div>
<p>One important thing to note is that in zsh the transformation occurs on strings but in haskell we use list as intermediate representation:</p>
<pre><code>zsh:
&quot;Holy grail&quot; ==( ${project:gs/ /-/} )=&gt; &quot;Holy<span class="highlight">-</span>grail&quot;
==( ${project:l} )=&gt; &quot;<span class="highlight">h</span>oly-grail&quot;
haskell
&quot;Holy grail&quot; ==( map toLower )=&gt; &quot;<span class="highlight">h</span>oly grail&quot;
==( splitOneOf &quot; -&quot; )=&gt; <span class="highlight">[</span>&quot;holy&quot;<span class="highlight">,</span>&quot;grail&quot;<span class="highlight">]</span>
==( intercalate &quot;-&quot; )=&gt; <span class="highlight">&quot;</span>holy<span class="highlight">-</span>grail<span class="highlight">&quot;</span></code></pre>
<h3 id="create-the-module-name">Create the module name</h3>
<p>The module name is a capitalized version of the project name where we remove dashes.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb15-1" title="1"><span class="co"># Capitalize a string</span></a>
<a class="sourceLine" id="cb15-2" title="2"><span class="fu">capitalize()</span><span class="kw">{</span></a>
<a class="sourceLine" id="cb15-3" title="3"> <span class="bu">local</span> <span class="va">str=</span><span class="st">&quot;</span><span class="va">$(</span><span class="ex">print</span> -- <span class="st">&quot;</span><span class="va">$*</span><span class="st">&quot;</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">&#39;s/-/ /g&#39;</span><span class="va">)</span><span class="st">&quot;</span></a>
<a class="sourceLine" id="cb15-4" title="4"> <span class="ex">print</span> -- $<span class="dt">{(C)str}</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">&#39;s/ //g&#39;</span></a>
<a class="sourceLine" id="cb15-5" title="5"><span class="kw">}</span></a></code></pre></div>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb16-1" title="1"><span class="co">-- | transform a chain like &quot;Holy project&quot; in &quot;HolyProject&quot;</span></a>
<a class="sourceLine" id="cb16-2" title="2"><span class="ot">capitalize ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb16-3" title="3">capitalize str <span class="ot">=</span> <span class="fu">concatMap</span> capitalizeWord (splitOneOf <span class="st">&quot; -&quot;</span> str)</a>
<a class="sourceLine" id="cb16-4" title="4"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb16-5" title="5"><span class="ot"> capitalizeWord ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb16-6" title="6"> capitalizeWord (x<span class="op">:</span>xs) <span class="ot">=</span> <span class="fu">toUpper</span> x<span class="op">:</span><span class="fu">map</span> <span class="fu">toLower</span> xs</a>
<a class="sourceLine" id="cb16-7" title="7"> capitalizeWord _ <span class="ot">=</span> []</a></code></pre></div>
<p>The haskell version is made by hand where zsh already had a capitalize operation on string with many words. Here is the difference between the shell and haskell way (note I splitted the effect of <code>concatMap</code> as <code>map</code> and <code>concat</code>):</p>
<pre><code>shell:
&quot;Holy-grail&quot; ==( sed &#39;s/-/ /g&#39; )=&gt; &quot;Holy<span class="highlight"> </span>grail&quot;
==( ${(C)str} )=&gt; &quot;Holy <span class="highlight">G</span>rail&quot;
==( sed &#39;s/ //g&#39; )=&gt; &quot;HolyGrail&quot;
haskell:
&quot;Holy-grail&quot; ==( splitOneOf &quot; -&quot; )=&gt; <span class="highlight">[</span>&quot;Holy&quot;<span class="highlight">,</span>&quot;grail&quot;<span class="highlight">]</span>
==( map capitalizeWord )=&gt; [&quot;Holy&quot;,&quot;<span class="highlight">G</span>rail&quot;]
==( concat )=&gt; &quot;HolyGrail&quot;</code></pre>
<p>As the preceding example, in shell we work on strings while Haskell use temporary lists representations.</p>
<h3 id="check-the-project-name">Check the project name</h3>
<p>Also I want to be quite restrictive on the kind of project name we can give. This is why I added a check function.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb18-1" title="1"><span class="ot">ioassert ::</span> <span class="dt">Bool</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb18-2" title="2">ioassert <span class="dt">True</span> _ <span class="ot">=</span> <span class="fu">return</span> ()</a>
<a class="sourceLine" id="cb18-3" title="3">ioassert <span class="dt">False</span> str <span class="ot">=</span> <span class="fu">error</span> str</a>
<a class="sourceLine" id="cb18-4" title="4"></a>
<a class="sourceLine" id="cb18-5" title="5"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb18-6" title="6">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb18-7" title="7"> intro</a>
<a class="sourceLine" id="cb18-8" title="8"> project <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span></a>
<a class="sourceLine" id="cb18-9" title="9"> ioassert (checkProjectName project)</a>
<a class="sourceLine" id="cb18-10" title="10"> <span class="st">&quot;Use only letters, numbers, spaces and dashes please&quot;</span></a>
<a class="sourceLine" id="cb18-11" title="11"> <span class="kw">let</span> projectname <span class="ot">=</span> projectNameFromString project</a>
<a class="sourceLine" id="cb18-12" title="12"> modulename <span class="ot">=</span> capitalize project</a></code></pre></div>
<p>Which verify the project name is not empty and use only letter, numbers and dashes:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb19-1" title="1"><span class="co">-- | verify if project name is conform</span></a>
<a class="sourceLine" id="cb19-2" title="2"><span class="ot">checkProjectName ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></a>
<a class="sourceLine" id="cb19-3" title="3">checkProjectName [] <span class="ot">=</span> <span class="dt">False</span></a>
<a class="sourceLine" id="cb19-4" title="4">checkProjectName str <span class="ot">=</span></a>
<a class="sourceLine" id="cb19-5" title="5"> <span class="fu">all</span> (\c <span class="ot">-&gt;</span> isLetter c <span class="op">||</span> isNumber c <span class="op">||</span> c<span class="op">==</span><span class="ch">&#39;-&#39;</span> <span class="op">||</span> c<span class="op">==</span><span class="ch">&#39; &#39;</span>) str</a></code></pre></div>
<h2 id="create-the-project">Create the project</h2>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/giant-three-head.jpg" alt="Giant with three heads and mustaches"/>
</div>
<p>Making a project will consists in creating files and directories whose name and content depends on the answer we had until now.</p>
<p>In shell, for each file to create, we used something like:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb20-1" title="1"><span class="op">&gt;</span> <span class="ex">file-to-create</span> cat <span class="op">&lt;&lt;END</span></a>
<a class="sourceLine" id="cb20-2" title="2">file content here.</a>
<a class="sourceLine" id="cb20-3" title="3">We can use <span class="va">$variables</span> here</a>
<a class="sourceLine" id="cb20-4" title="4"><span class="op">END</span></a></code></pre></div>
<p>In Haskell, while possible, we shouldnt put the file content in the source code. We have a relatively easy way to include external file in a cabal package. This is what we will be using.</p>
<p>Furthermore, we need a templating system to replace small part of the static file by computed values. For this task, I choose to use <a href="http://hackage.haskell.org/package/hastache"><code>hastache</code></a>, a Haskell implementation of Mustache templates<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>.</p>
<h3 id="add-external-files-in-a-cabal-project">Add external files in a cabal project</h3>
<p>Cabal provides a way to add files which are not source files to a package. You simply have to add a <code>Data-Files:</code> entry in the header of the cabal file:</p>
<pre><code>data-files: scaffold/LICENSE
, scaffold/Setup.hs
, scaffold/auto-update
, scaffold/gitignore
, scaffold/interact
, scaffold/project.cabal
, scaffold/src/Main.hs
, scaffold/src/ModuleName.hs
, scaffold/src/ModuleName/Coconut.hs
, scaffold/src/ModuleName/Swallow.hs
, scaffold/test/ModuleName/Coconut/Test.hs
, scaffold/test/ModuleName/Swallow/Test.hs
, scaffold/test/Test.hs</code></pre>
<p>Now we simply have to create our files at the specified path. Here is for example the first lines of the LICENSE file.</p>
<pre class="mustache"><code>The MIT License (MIT)
Copyright (c) <span class="highlight">{{year}}</span> <span class="highlight">{{author}}</span>
Permission is hereby granted, free of charge, to any person obtaining a copy
...</code></pre>
<p>It will be up to our program to replace the <code>{{year}}</code> and <code>{{author}}</code> at runtime. We have to find the files. Cabal will create a module named <code>Paths_holy_project</code>. If we import this module we have the function <code>genDataFileName</code> at our disposal. Now we can read the files at runtime like this:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb23-1" title="1"> <span class="op">...</span></a>
<a class="sourceLine" id="cb23-2" title="2"> <span class="kw">do</span></a>
<a class="sourceLine" id="cb23-3" title="3"> pkgFilePath <span class="ot">&lt;-</span> <span class="highlight">getDataFileName <span class="st">&quot;scaffold/LICENSE&quot;</span></span></a>
<a class="sourceLine" id="cb23-4" title="4"> templateContent <span class="ot">&lt;-</span> <span class="fu">readFile</span> pkgFilePath</a>
<a class="sourceLine" id="cb23-5" title="5"> <span class="op">...</span></a></code></pre></div>
<h3 id="create-files-and-directories">Create files and directories</h3>
<p>A first remark is for portability purpose we shouldnt use String for file path. For example on Windows <code>/</code> isnt considered as a subdirectory character. To resolve this problem we will use <code>FilePath</code>:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb24-1" title="1"><span class="kw">import</span> <span class="dt">System.Directory</span></a>
<a class="sourceLine" id="cb24-2" title="2"><span class="kw">import</span> <span class="dt">System.FilePath.Posix</span> (takeDirectory,(&lt;/&gt;))</a>
<a class="sourceLine" id="cb24-3" title="3"><span class="op">...</span></a>
<a class="sourceLine" id="cb24-4" title="4">createProject <span class="op">...</span> <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb24-5" title="5"> <span class="op">...</span></a>
<a class="sourceLine" id="cb24-6" title="6"> <span class="highlight">createDirectory</span> projectName <span class="co">-- mkdir</span></a>
<a class="sourceLine" id="cb24-7" title="7"> <span class="highlight">setCurrentDirectory</span> projectName <span class="co">-- cd</span></a>
<a class="sourceLine" id="cb24-8" title="8"> genFile <span class="st">&quot;LICENSE&quot;</span> <span class="st">&quot;LICENSE&quot;</span></a>
<a class="sourceLine" id="cb24-9" title="9"> genFile <span class="st">&quot;gitignore&quot;</span> <span class="st">&quot;.gitignore&quot;</span></a>
<a class="sourceLine" id="cb24-10" title="10"> genFile <span class="st">&quot;src/Main.hs&quot;</span> (<span class="st">&quot;src&quot;</span> <span class="op">&lt;/&gt;</span> <span class="st">&quot;Main.hs&quot;</span>)</a>
<a class="sourceLine" id="cb24-11" title="11"></a>
<a class="sourceLine" id="cb24-12" title="12">genFile dataFilename outputFilename <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb24-13" title="13"> pkgfileName <span class="ot">&lt;-</span> getDataFileName (<span class="st">&quot;scaffold/&quot;</span> <span class="op">++</span> filename)</a>
<a class="sourceLine" id="cb24-14" title="14"> template <span class="ot">&lt;-</span> <span class="fu">readFile</span> pkgfileName</a>
<a class="sourceLine" id="cb24-15" title="15"> transformedFile <span class="ot">&lt;-</span> <span class="op">???</span> <span class="co">-- hastache magic here</span></a>
<a class="sourceLine" id="cb24-16" title="16"> <span class="highlight">createDirectoryIfMissing</span> <span class="dt">True</span> (takeDirectory outputFileName)</a>
<a class="sourceLine" id="cb24-17" title="17"> <span class="highlight"><span class="fu">writeFile</span></span> outputFileName transformedFile</a></code></pre></div>
<h3 id="use-hastache">Use Hastache</h3>
<p>In order to use hastache we can either create a context manually or use generics to create a context from a record. This is the last option we will show here. So in a first time, we need to import some modules and declare a record containing all necessary informations to create our project.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb25-1" title="1"><span class="ot">{-# LANGUAGE DeriveDataTypeable #-}</span></a>
<a class="sourceLine" id="cb25-2" title="2"><span class="op">...</span></a>
<a class="sourceLine" id="cb25-3" title="3"><span class="kw">import</span> <span class="dt">Data.Data</span></a>
<a class="sourceLine" id="cb25-4" title="4"><span class="kw">import</span> <span class="dt">Text.Hastache</span></a>
<a class="sourceLine" id="cb25-5" title="5"><span class="kw">import</span> <span class="dt">Text.Hastache.Context</span></a>
<a class="sourceLine" id="cb25-6" title="6"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">BS</span></a>
<a class="sourceLine" id="cb25-7" title="7"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString.Lazy.Char8</span> <span class="kw">as</span> <span class="dt">LZ</span></a></code></pre></div>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb26-1" title="1"><span class="kw">data</span> <span class="dt">Project</span> <span class="ot">=</span> <span class="dt">Project</span> {</a>
<a class="sourceLine" id="cb26-2" title="2"><span class="ot"> projectName ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-3" title="3"> ,<span class="ot"> moduleName ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-4" title="4"> ,<span class="ot"> author ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-5" title="5"> ,<span class="ot"> mail ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-6" title="6"> ,<span class="ot"> ghaccount ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-7" title="7"> ,<span class="ot"> synopsis ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-8" title="8"> ,<span class="ot"> year ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-9" title="9"> } <span class="kw">deriving</span> (<span class="dt">Data</span>, <span class="dt">Typeable</span>)</a></code></pre></div>
<p>Once we have declared this, we should populate our Project record with the data provided by the user. So our main function should look like:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb27-1" title="1"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb27-2" title="2">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb27-3" title="3"> intro</a>
<a class="sourceLine" id="cb27-4" title="4"> project <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span></a>
<a class="sourceLine" id="cb27-5" title="5"> ioassert (checkProjectName project)</a>
<a class="sourceLine" id="cb27-6" title="6"> <span class="st">&quot;Use only letters, numbers, spaces and dashes please&quot;</span></a>
<a class="sourceLine" id="cb27-7" title="7"> <span class="kw">let</span> projectname <span class="ot">=</span> projectNameFromString project</a>
<a class="sourceLine" id="cb27-8" title="8"> modulename <span class="ot">=</span> capitalize project</a>
<a class="sourceLine" id="cb27-9" title="9"> <span class="highlight">in_author</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;name&quot;</span></a>
<a class="sourceLine" id="cb27-10" title="10"> <span class="highlight">in_email</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;email&quot;</span></a>
<a class="sourceLine" id="cb27-11" title="11"> <span class="highlight">in_ghaccount</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;github account&quot;</span></a>
<a class="sourceLine" id="cb27-12" title="12"> <span class="highlight">in_synopsis</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;project in less than a dozen word?&quot;</span></a>
<a class="sourceLine" id="cb27-13" title="13"> <span class="highlight">current_year</span> <span class="ot">&lt;-</span> getCurrentYear</a>
<a class="sourceLine" id="cb27-14" title="14"> createProject <span class="op">$</span> <span class="highlight"><span class="dt">Project</span> projectname modulename in_author in_email</span></a>
<a class="sourceLine" id="cb27-15" title="15"> <span class="highlight">in_ghaccount in_synopsis current_year</span></a>
<a class="sourceLine" id="cb27-16" title="16"> end</a></code></pre></div>
<p>Finally we could use hastache this way:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb28-1" title="1"><span class="ot">createProject ::</span> <span class="highlight"><span class="dt">Project</span></span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb28-2" title="2">createProject <span class="highlight">p</span> <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb28-3" title="3"> <span class="kw">let</span> <span class="highlight">context</span> <span class="ot">=</span> <span class="highlight">mkGenericContext p</span></a>
<a class="sourceLine" id="cb28-4" title="4"> createDirectory (<span class="highlight">projectName p</span>)</a>
<a class="sourceLine" id="cb28-5" title="5"> setCurrentDirectory (<span class="highlight">projectName p</span>)</a>
<a class="sourceLine" id="cb28-6" title="6"> genFile <span class="highlight">context</span> <span class="st">&quot;gitignore&quot;</span> <span class="op">$</span> <span class="st">&quot;.gitignore&quot;</span></a>
<a class="sourceLine" id="cb28-7" title="7"> genFile <span class="highlight">context</span> <span class="st">&quot;project.cabal&quot;</span> <span class="op">$</span> (projectName p) <span class="op">++</span> <span class="st">&quot;.cabal&quot;</span></a>
<a class="sourceLine" id="cb28-8" title="8"> genFile <span class="highlight">context</span> <span class="st">&quot;src/Main.hs&quot;</span>) <span class="op">$</span> <span class="st">&quot;src&quot;</span> <span class="op">&lt;/&gt;</span> <span class="st">&quot;Main.hs&quot;</span></a>
<a class="sourceLine" id="cb28-9" title="9"> <span class="op">...</span></a>
<a class="sourceLine" id="cb28-10" title="10"></a>
<a class="sourceLine" id="cb28-11" title="11"><span class="ot">genFile ::</span> <span class="dt">MuContext</span> <span class="dt">IO</span> <span class="ot">-&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb28-12" title="12">genFile context filename outputFileName <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb28-13" title="13"> pkgfileName <span class="ot">&lt;-</span> getDataFileName (<span class="st">&quot;scaffold/&quot;</span><span class="op">++</span>filename)</a>
<a class="sourceLine" id="cb28-14" title="14"> template <span class="ot">&lt;-</span> <span class="highlight"><span class="dt">BS</span><span class="op">.</span></span><span class="fu">readFile</span> pkgfileName</a>
<a class="sourceLine" id="cb28-15" title="15"> transformedFile <span class="ot">&lt;-</span> <span class="highlight">hastacheStr defaultConfig template context</span></a>
<a class="sourceLine" id="cb28-16" title="16"> createDirectoryIfMissing <span class="dt">True</span> (takeDirectory outputFileName)</a>
<a class="sourceLine" id="cb28-17" title="17"> <span class="highlight"><span class="dt">LZ</span><span class="op">.</span></span><span class="fu">writeFile</span> outputFileName transformedFile</a></code></pre></div>
<p>We use external files in mustache format. We ask question to our user to fill a data structure. We use this data structure to create a context. Hastache use this context with the external files to create the project files.</p>
<h2 id="git-and-cabal">Git and Cabal</h2>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/tim.jpg" alt="Tim"/>
</div>
<p>We need to initialize git and cabal. For this we simply call external command with the <code>system</code> function.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb29-1" title="1"><span class="kw">import</span> <span class="dt">System.Cmd</span></a>
<a class="sourceLine" id="cb29-2" title="2"></a>
<a class="sourceLine" id="cb29-3" title="3"><span class="op">...</span></a>
<a class="sourceLine" id="cb29-4" title="4">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb29-5" title="5"> <span class="op">...</span></a>
<a class="sourceLine" id="cb29-6" title="6"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;git init .&quot;</span></a>
<a class="sourceLine" id="cb29-7" title="7"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;cabal sandbox init&quot;</span></a>
<a class="sourceLine" id="cb29-8" title="8"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;cabal install&quot;</span></a>
<a class="sourceLine" id="cb29-9" title="9"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;cabal test&quot;</span></a>
<a class="sourceLine" id="cb29-10" title="10"> _ <span class="ot">&lt;-</span> system <span class="op">$</span> <span class="st">&quot;./.cabal-sandbox/bin/test-&quot;</span> <span class="op">++</span> projectName</a></code></pre></div>
<h2 id="ameliorations">Ameliorations</h2>
<p>Our job is almost finished. Now, we only need to add some nice feature to make the application more enjoyable.</p>
<h3 id="better-error-message">Better error message</h3>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/rabbit.jpg" alt="Rabbit"/>
</div>
<p>The first one would be to add a better error message.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb30-1" title="1"><span class="kw">import</span> <span class="dt">System.Random</span></a>
<a class="sourceLine" id="cb30-2" title="2"></a>
<a class="sourceLine" id="cb30-3" title="3"><span class="ot">holyError ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb30-4" title="4">holyError str <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb30-5" title="5"> r <span class="ot">&lt;-</span> randomIO</a>
<a class="sourceLine" id="cb30-6" title="6"> <span class="kw">if</span> r</a>
<a class="sourceLine" id="cb30-7" title="7"> <span class="kw">then</span></a>
<a class="sourceLine" id="cb30-8" title="8"> <span class="kw">do</span></a>
<a class="sourceLine" id="cb30-9" title="9"> bk <span class="st">&quot;What... is your favourite colour?&quot;</span></a>
<a class="sourceLine" id="cb30-10" title="10"> you <span class="st">&quot;Blue. No, yel...&quot;</span></a>
<a class="sourceLine" id="cb30-11" title="11"> <span class="fu">putStrLn</span> <span class="st">&quot;[You are thrown over the edge into the volcano]&quot;</span></a>
<a class="sourceLine" id="cb30-12" title="12"> you <span class="st">&quot;You: Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb30-13" title="13"> bk <span class="st">&quot; Hee hee heh.&quot;</span></a>
<a class="sourceLine" id="cb30-14" title="14"> <span class="kw">else</span></a>
<a class="sourceLine" id="cb30-15" title="15"> <span class="kw">do</span></a>
<a class="sourceLine" id="cb30-16" title="16"> bk <span class="st">&quot;What is the capital of Assyria?&quot;</span></a>
<a class="sourceLine" id="cb30-17" title="17"> you <span class="st">&quot;I don&#39;t know that!&quot;</span></a>
<a class="sourceLine" id="cb30-18" title="18"> <span class="fu">putStrLn</span> <span class="st">&quot;[You are thrown over the edge into the volcano]&quot;</span></a>
<a class="sourceLine" id="cb30-19" title="19"> you <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb30-20" title="20"> <span class="fu">error</span> (<span class="ch">&#39;\n&#39;</span><span class="op">:</span>str)</a></code></pre></div>
<p>And also update where this can be called</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb31-1" title="1"><span class="ot">ioassert ::</span> <span class="dt">Bool</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb31-2" title="2">ioassert <span class="dt">True</span> _ <span class="ot">=</span> <span class="fu">return</span> ()</a>
<a class="sourceLine" id="cb31-3" title="3">ioassert <span class="dt">False</span> str <span class="ot">=</span> holyError str</a></code></pre></div>
<h3 id="use-.gitconfig">Use <code>.gitconfig</code></h3>
<p>We want to retrieve the <code>~/.gitconfig</code> file content and see if it contains a name and email information. We will need to access to the <code>HOME</code> environment variable. Also, as we use bytestring package for hastache, lets take advantage of this library.</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb32-1" title="1"><span class="kw">import</span> <span class="dt">Data.Maybe</span> (fromJust)</a>
<a class="sourceLine" id="cb32-2" title="2"><span class="kw">import</span> <span class="dt">System.Environment</span> (getEnv)</a>
<a class="sourceLine" id="cb32-3" title="3"><span class="kw">import</span> <span class="dt">Control.Exception</span></a>
<a class="sourceLine" id="cb32-4" title="4"><span class="kw">import</span> <span class="dt">System.IO.Error</span></a>
<a class="sourceLine" id="cb32-5" title="5"><span class="kw">import</span> <span class="dt">Control.Monad</span> (guard)</a>
<a class="sourceLine" id="cb32-6" title="6"></a>
<a class="sourceLine" id="cb32-7" title="7"><span class="ot">safeReadGitConfig ::</span> <span class="dt">IO</span> <span class="dt">LZ.ByteString</span></a>
<a class="sourceLine" id="cb32-8" title="8">safeReadGitConfig <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb32-9" title="9"> e <span class="ot">&lt;-</span> tryJust (guard <span class="op">.</span> isDoesNotExistError)</a>
<a class="sourceLine" id="cb32-10" title="10"> (<span class="kw">do</span></a>
<a class="sourceLine" id="cb32-11" title="11"> home <span class="ot">&lt;-</span> getEnv <span class="st">&quot;HOME&quot;</span></a>
<a class="sourceLine" id="cb32-12" title="12"> LZ.readFile <span class="op">$</span> home <span class="op">++</span> <span class="st">&quot;/.gitconfig&quot;</span> )</a>
<a class="sourceLine" id="cb32-13" title="13"> <span class="fu">return</span> <span class="op">$</span> <span class="fu">either</span> (<span class="fu">const</span> (LZ.empty)) <span class="fu">id</span> e</a>
<a class="sourceLine" id="cb32-14" title="14"><span class="op">...</span></a>
<a class="sourceLine" id="cb32-15" title="15">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb32-16" title="16"> gitconfig <span class="ot">&lt;-</span> safeReadGitConfig</a>
<a class="sourceLine" id="cb32-17" title="17"> <span class="kw">let</span> (name,email) <span class="ot">=</span> <span class="highlight">getNameAndMail</span> gitconfig</a>
<a class="sourceLine" id="cb32-18" title="18"> project <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb32-19" title="19"> <span class="op">...</span></a>
<a class="sourceLine" id="cb32-20" title="20"> in_author <span class="ot">&lt;-</span> ask <span class="st">&quot;name&quot;</span> name</a>
<a class="sourceLine" id="cb32-21" title="21"> <span class="op">...</span></a></code></pre></div>
<p>We could note I changed the ask function slightly to take a maybe parameter.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb33-1" title="1"><span class="ot">ask ::</span> <span class="dt">String</span> <span class="highlight"><span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span></span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb33-2" title="2">ask info hint <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb33-3" title="3"> bk <span class="op">$</span> <span class="st">&quot;What is your &quot;</span> <span class="op">++</span> info <span class="op">++</span> <span class="st">&quot;?&quot;</span> <span class="op">++</span> <span class="highlight">(<span class="fu">maybe</span> <span class="st">&quot;&quot;</span> (\h <span class="ot">-&gt;</span> <span class="st">&quot; (&quot;</span><span class="op">++</span>h<span class="op">++</span><span class="st">&quot;)&quot;</span>) hint)</span></a>
<a class="sourceLine" id="cb33-4" title="4"> <span class="op">...</span></a></code></pre></div>
<p>Concerning the parsing of <code>.gitconfig</code>, it is quite minimalist.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb34-1" title="1"><span class="ot">getNameAndMail ::</span> <span class="dt">LZ.ByteString</span> <span class="ot">-&gt;</span> (<span class="dt">Maybe</span> <span class="dt">String</span>,<span class="dt">Maybe</span> <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb34-2" title="2">getNameAndMail gitConfigContent <span class="ot">=</span> (getFirstValueFor splitted <span class="st">&quot;name&quot;</span>,</a>
<a class="sourceLine" id="cb34-3" title="3"> getFirstValueFor splitted <span class="st">&quot;email&quot;</span>)</a>
<a class="sourceLine" id="cb34-4" title="4"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb34-5" title="5"> <span class="co">-- make lines of words</span></a>
<a class="sourceLine" id="cb34-6" title="6"><span class="ot"> splitted ::</span> [[<span class="dt">LZ.ByteString</span>]]</a>
<a class="sourceLine" id="cb34-7" title="7"> splitted <span class="ot">=</span> <span class="fu">map</span> LZ.words (LZ.lines gitConfigContent)</a>
<a class="sourceLine" id="cb34-8" title="8"></a>
<a class="sourceLine" id="cb34-9" title="9"><span class="co">-- Get the first line which start with</span></a>
<a class="sourceLine" id="cb34-10" title="10"><span class="co">-- &#39;elem =&#39; and return the third field (value)</span></a>
<a class="sourceLine" id="cb34-11" title="11"><span class="ot">getFirstValueFor ::</span> [[<span class="dt">LZ.ByteString</span>]] <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb34-12" title="12">getFirstValueFor splitted key <span class="ot">=</span> firstJust (<span class="fu">map</span> (getValueForKey key) splitted)</a>
<a class="sourceLine" id="cb34-13" title="13"></a>
<a class="sourceLine" id="cb34-14" title="14"><span class="co">-- return the first Just value of a list of Maybe</span></a>
<a class="sourceLine" id="cb34-15" title="15"><span class="ot">firstJust ::</span> (<span class="dt">Eq</span> a) <span class="ot">=&gt;</span> [<span class="dt">Maybe</span> a] <span class="ot">-&gt;</span> <span class="dt">Maybe</span> a</a>
<a class="sourceLine" id="cb34-16" title="16">firstJust l <span class="ot">=</span> <span class="kw">case</span> <span class="fu">dropWhile</span> (<span class="op">==</span><span class="dt">Nothing</span>) l <span class="kw">of</span></a>
<a class="sourceLine" id="cb34-17" title="17"> [] <span class="ot">-&gt;</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb34-18" title="18"> (j<span class="op">:</span>_) <span class="ot">-&gt;</span> j</a>
<a class="sourceLine" id="cb34-19" title="19"></a>
<a class="sourceLine" id="cb34-20" title="20"><span class="co">-- Given a line of words (&quot;word1&quot;:&quot;word2&quot;:rest)</span></a>
<a class="sourceLine" id="cb34-21" title="21"><span class="co">-- getValue will return rest if word1 == key</span></a>
<a class="sourceLine" id="cb34-22" title="22"><span class="co">-- &#39;elem =&#39; or Nothing otherwise</span></a>
<a class="sourceLine" id="cb34-23" title="23"><span class="ot">getValueForKey ::</span> <span class="dt">String</span> <span class="co">-- key</span></a>
<a class="sourceLine" id="cb34-24" title="24"> <span class="ot">-&gt;</span> [<span class="dt">LZ.ByteString</span>] <span class="co">-- line of words</span></a>
<a class="sourceLine" id="cb34-25" title="25"> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span> <span class="co">-- the value if found</span></a>
<a class="sourceLine" id="cb34-26" title="26">getValueForKey el (n<span class="op">:</span>e<span class="op">:</span>xs) <span class="ot">=</span> <span class="kw">if</span> (n <span class="op">==</span> (LZ.pack el)) <span class="op">&amp;&amp;</span> (e <span class="op">==</span> (LZ.pack <span class="st">&quot;=&quot;</span>))</a>
<a class="sourceLine" id="cb34-27" title="27"> <span class="kw">then</span> <span class="dt">Just</span> (LZ.unpack (LZ.unwords xs))</a>
<a class="sourceLine" id="cb34-28" title="28"> <span class="kw">else</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb34-29" title="29">getValueForKey _ _ <span class="ot">=</span> <span class="dt">Nothing</span></a></code></pre></div>
<p>We could notice, <code>getNameAndMail</code> doesnt read the full file and stop at the first occurrence of name and mail.</p>
<h3 id="use-the-github-api">Use the github API</h3>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/coconut.jpg" alt="Coconut and Swallow"/>
</div>
<p>The task seems relatively easy, but well see there will be some complexity hidden. Make a request on <code>https://api.github.com/search/users?q=&lt;email&gt;</code>. Parse the JSON and get the <code>login</code> field of the first item.</p>
<p>So the first problem to handle is to connect an URL. For this we will use the <code>http-conduit</code> package.</p>
<p>Generally, for simple request, we should use:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb35-1" title="1"><span class="kw">do</span></a>
<a class="sourceLine" id="cb35-2" title="2"> body <span class="ot">&lt;-</span> simpleHTTP (<span class="st">&quot;https://api.github.com/search/users?q=&quot;</span> <span class="op">++</span> email)</a>
<a class="sourceLine" id="cb35-3" title="3"> <span class="op">...</span></a></code></pre></div>
<p>But, after some research, I discovered we must declare an User-Agent in the HTTP header to be accepted by the github API. So we have to change the HTTP Header, and our code became slightly more complex:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb36-1" title="1"><span class="ot">{-# LANGUAGE OverloadedStrings #-}</span></a>
<a class="sourceLine" id="cb36-2" title="2"><span class="op">...</span></a>
<a class="sourceLine" id="cb36-3" title="3"><span class="ot">simpleHTTPWithUserAgent ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">LZ.ByteString</span></a>
<a class="sourceLine" id="cb36-4" title="4">simpleHTTPWithUserAgent url <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb36-5" title="5"> r <span class="ot">&lt;-</span> parseUrl url</a>
<a class="sourceLine" id="cb36-6" title="6"> <span class="kw">let</span> request <span class="ot">=</span> r { requestHeaders <span class="ot">=</span> [ (<span class="st">&quot;User-Agent&quot;</span>,<span class="st">&quot;HTTP-Conduit&quot;</span>) ] }</a>
<a class="sourceLine" id="cb36-7" title="7"> withManager <span class="op">$</span> (<span class="fu">return</span><span class="op">.</span>responseBody) <span class="op">&lt;=&lt;</span> httpLbs request</a>
<a class="sourceLine" id="cb36-8" title="8"></a>
<a class="sourceLine" id="cb36-9" title="9"><span class="ot">getGHUser ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Maybe</span> <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb36-10" title="10">getGHUser <span class="st">&quot;&quot;</span> <span class="ot">=</span> <span class="fu">return</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb36-11" title="11">getGHUser email <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb36-12" title="12"> <span class="kw">let</span> url <span class="ot">=</span> <span class="st">&quot;https://api.github.com/search/users?q=&quot;</span> <span class="op">++</span> email</a>
<a class="sourceLine" id="cb36-13" title="13"> body <span class="ot">&lt;-</span> simpleHTTPWithUserAgent url</a>
<a class="sourceLine" id="cb36-14" title="14"> <span class="op">...</span></a></code></pre></div>
<p>So now, we have a String containing a JSON representation. In javascript we would have used <code>login=JSON.parse(body).items[0].login</code>. How does Haskell will handle it (knowing the J in JSON is for Javascript)?</p>
<p>First we will need to add the <code>lens-aeson</code> package and use it that way:</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb37-1" title="1"><span class="kw">import</span> <span class="dt">Control.Lens.Operators</span> ((^?))</a>
<a class="sourceLine" id="cb37-2" title="2"><span class="kw">import</span> <span class="dt">Control.Lens.Aeson</span></a>
<a class="sourceLine" id="cb37-3" title="3"><span class="kw">import</span> <span class="dt">Data.Aeson.Encode</span> (fromValue)</a>
<a class="sourceLine" id="cb37-4" title="4"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text.Lazy</span> <span class="kw">as</span> <span class="dt">TLZ</span></a>
<a class="sourceLine" id="cb37-5" title="5"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text.Lazy.Builder</span> <span class="kw">as</span> <span class="dt">TLB</span></a>
<a class="sourceLine" id="cb37-6" title="6"></a>
<a class="sourceLine" id="cb37-7" title="7"><span class="ot">getGHUser ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Maybe</span> <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb37-8" title="8">getGHUser email <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb37-9" title="9"> <span class="kw">let</span> url <span class="ot">=</span> <span class="st">&quot;https://api.github.com/search/users?q=&quot;</span> <span class="op">++</span> email</a>
<a class="sourceLine" id="cb37-10" title="10"> body <span class="ot">&lt;-</span> simpleHTTPWithUserAgent url</a>
<a class="sourceLine" id="cb37-11" title="11"> <span class="kw">let</span> login <span class="ot">=</span> <span class="highlight">body <span class="op">^?</span> key <span class="st">&quot;items&quot;</span> <span class="op">.</span> nth <span class="dv">0</span> <span class="op">.</span> key <span class="st">&quot;login&quot;</span></span></a>
<a class="sourceLine" id="cb37-12" title="12"> <span class="fu">return</span> <span class="op">$</span> <span class="fu">fmap</span> jsonValueToString login</a>
<a class="sourceLine" id="cb37-13" title="13"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb37-14" title="14"> jsonValueToString <span class="ot">=</span> TLZ.unpack <span class="op">.</span> TLB.toLazyText <span class="op">.</span> fromValue</a></code></pre></div>
<p>It looks ugly, but its terse. In fact each function <code>(^?)</code>, <code>key</code> and <code>nth</code> has some great mathematical properties and everything is type safe. Unfortunately I had to make my own <code>jsonValueToString</code>. I hope I simply missed a simpler existing function.</p>
<p>You can read <a href="https://www.fpcomplete.com/user/tel/lens-aeson-traversals-prisms">this article on <code>lens-aeson</code> and prisms</a> to know more.</p>
<h4 id="concurrency">Concurrency</h4>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/priest.jpg" alt="Priests"/>
</div>
<p>We now have all the feature provided by the original <code>zsh</code> script shell. But here is a good occasion to use some Haskell great feature.</p>
<p>We will launch the API request sooner and in parallel to minimize our wait time:</p>
<pre><code>import Control.Concurrent
...
main :: IO ()
main = do
intro
gitconfig &lt;- safeReadGitConfig
let (name,email) = getNameAndMail gitconfig
<span class="highlight">earlyhint &lt;- newEmptyMVar</span>
<span class="highlight">maybe (putMVar earlyhint Nothing)</span> -- if no email found put Nothing
<span class="highlight">(\hintmail -&gt; do</span> -- in the other case request the github API
<span class="highlight">forkIO (putMVar earlyhint =&lt;&lt; getGHUser hintmail)</span>
<span class="highlight">return ())</span>
<span class="highlight">email</span>
project &lt;- ask &quot;project name&quot; Nothing
ioassert (checkProjectName project)
&quot;Use only letters, numbers, spaces and dashes please&quot;
let projectname = projectNameFromString project
modulename = capitalize project
in_author &lt;- ask &quot;name&quot; name
in_email &lt;- ask &quot;email&quot; email
<span class="highlight">ghUserHint &lt;- if maybe &quot;&quot; id email /= in_email</span>
<span class="highlight">then getGHUser in_email</span>
<span class="highlight">else takeMVar earlyhint</span>
in_ghaccount &lt;- ask &quot;github account&quot; ghUserHint
in_synopsis &lt;- ask &quot;project in less than a dozen word?&quot; Nothing
current_year &lt;- getCurrentYear
createProject $ Project projectname modulename in_author in_email
in_ghaccount in_synopsis current_year
end</code></pre>
<p>While it might feel a bit confusing, it is in fact quite simple.</p>
<ol type="1">
<li>declare an <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent-MVar.html"><code>MVar</code></a>. Mainly a variable which either is empty or contains something.</li>
<li>If we didnt found any email hint, put Nothing in the <code>MVar</code>.</li>
<li>If we have an email hint, ask on the github API in a new process and once finished put the result in the <code>MVar</code>.</li>
<li>If the user enter an email different from the hint email, then just request the github api now.</li>
<li>If the user enter the same email, then wait for the MVar to be filled and ask the next question with the result.</li>
</ol>
<p>If you have a github account and had set correctly your <code>.gitconfig</code>, you might not even wait.</p>
<h2 id="project-structure">Project Structure</h2>
<p>We have a working product. But, I dont consider our job finished. The code is about 335 lines.</p>
<p>Considering that we:</p>
<ul>
<li>have 29 lines of import and 52 lines of comments (rest 255 lines)</li>
<li>ask questions</li>
<li>use a templating system to generate files</li>
<li>call an asynchronous HTTP request</li>
<li>parse JSON</li>
<li>parse <code>.gitconfig</code></li>
<li>use colored output</li>
</ul>
<p>This is quite few.</p>
<h3 id="modularizing">Modularizing</h3>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/black-knight.jpg" alt="The Black Knight"/>
</div>
<p>For short programs it is not obvious to split them into different modules. But my personal preference is to split it anyway.</p>
<p>First we put all content of <code>src/Main.hs</code> in <code>src/HolyProject.hs</code>. We rename the <code>main</code> function by <code>holyStarter</code>. And our <code>src/Main.hs</code> should contains:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb39-1" title="1"><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb39-2" title="2"><span class="kw">import</span> <span class="dt">HolyProject</span></a>
<a class="sourceLine" id="cb39-3" title="3"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb39-4" title="4">main <span class="ot">=</span> holyStarter</a></code></pre></div>
<p>Of course you have to remember to rename the module of <code>src/HolyProject.hs</code>. I separated all functions in different submodules:</p>
<ul>
<li><code>HolyProject.GitConfig</code>
<ul>
<li><code>getNameAndMailFromGitConfig</code>: retrieve name an email from <code>.gitconfig</code> file</li>
</ul></li>
<li><code>HolyProject.GithubAPI</code>
<ul>
<li><code>searchGHUser</code>: retrieve github user name using github API.</li>
</ul></li>
<li><code>HolyProject.MontyPython</code>
<ul>
<li><code>bk</code>: bridge keeper speaks</li>
<li><code>you</code>: you speak</li>
<li><code>ask</code>: Ask a question and wait for an answer</li>
</ul></li>
<li><code>HolyProject.StringUtils</code>: String helper functions
<ul>
<li><code>projectNameFromString</code></li>
<li><code>capitalize</code></li>
<li><code>checkProjectName</code></li>
</ul></li>
</ul>
<p>The <code>HolyProject.hs</code> file contains mostly the code that ask questions, show errors and copy files using hastache.</p>
<p>One of the benefits in modularizing the code is that our main code is clearer. Some functions are declared only in a module and are not exported. This help us hide technical details. For example, the modification of the HTTP header to use the github API.</p>
<h3 id="documenting">Documenting</h3>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/holy-grenade.jpg" alt="The Holy Grenade"/>
</div>
<p>We didnt take much advantage of the project structure yet. A first thing is to generate some documentation. Before most function I added comment starting with <code>-- |</code>. These comment will be used by haddock to create a documentation. First, you need to install <code>haddock</code> manually.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb40-1" title="1"><span class="ex">cabal</span> install haddock</a></code></pre></div>
<p>Be sure to have <code>haddock</code> in your <code>PATH</code>. You could for example add it like this:</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb41-1" title="1"><span class="co"># You might want to add this line in your .profile</span></a>
<a class="sourceLine" id="cb41-2" title="2"><span class="bu">export</span> <span class="va">PATH=$PATH</span>:./.cabal-sandbox/bin</a></code></pre></div>
<p>And if you are at the root of your project youll get it. And now just launch:</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb42-1" title="1"><span class="ex">cabal</span> haddock</a></code></pre></div>
<p>And magically, youll have a documentation in <code>dist/doc/html/holy-project/index.html</code>.</p>
<h3 id="tests">Tests</h3>
<p>While the Haskell static typing is quite efficient to prevent entire classes of bugs, Haskell doesnt discard the need to test to minimize the number of bugs.</p>
<h4 id="unit-testing-with-hunit">Unit Testing with HUnit</h4>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/witch.jpg" alt="A Witch! A Witch!"/>
</div>
<p>It is generally said to test we should use unit testing for code in IO and QuickCheck or SmallCheck for pure code.</p>
<p>A unit test example on pure code is in the file <code>test/HolyProject/Swallow/Test.hs</code>:</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb43-1" title="1"><span class="kw">module</span> <span class="dt">HolyProject.Swallow.Test</span></a>
<a class="sourceLine" id="cb43-2" title="2"> (swallowSuite)</a>
<a class="sourceLine" id="cb43-3" title="3"><span class="kw">where</span></a>
<a class="sourceLine" id="cb43-4" title="4"><span class="kw">import</span> <span class="dt">Test.Tasty</span> (testGroup, <span class="dt">TestTree</span>)</a>
<a class="sourceLine" id="cb43-5" title="5"><span class="kw">import</span> <span class="dt">Test.Tasty.HUnit</span></a>
<a class="sourceLine" id="cb43-6" title="6"><span class="kw">import</span> <span class="dt">HolyProject.Swallow</span> (<span class="highlight">swallow</span>)</a>
<a class="sourceLine" id="cb43-7" title="7"></a>
<a class="sourceLine" id="cb43-8" title="8"><span class="ot">swallowSuite ::</span> <span class="dt">TestTree</span></a>
<a class="sourceLine" id="cb43-9" title="9">swallowSuite <span class="ot">=</span> testGroup <span class="st">&quot;Swallow&quot;</span></a>
<a class="sourceLine" id="cb43-10" title="10"> [testCase <span class="st">&quot;swallow test&quot;</span> testSwallow]</a>
<a class="sourceLine" id="cb43-11" title="11"></a>
<a class="sourceLine" id="cb43-12" title="12"><span class="co">-- in Swallow: swallow = (++)</span></a>
<a class="sourceLine" id="cb43-13" title="13"><span class="ot">testSwallow ::</span> <span class="dt">Assertion</span></a>
<a class="sourceLine" id="cb43-14" title="14">testSwallow <span class="ot">=</span> <span class="st">&quot;something&quot;</span> <span class="op">@=?</span> <span class="highlight">swallow</span> <span class="st">&quot;some&quot;</span> <span class="st">&quot;thing&quot;</span></a></code></pre></div>
<p>Note <code>swallow</code> is <code>(++)</code>. We group tests by group. Each group can contain some test suite. Here we have a test suite with only one test. The <code>(@=?)</code> verify the equality between its two parameters.</p>
<p>So now, we could safely delete the directory <code>test/HolyProject/Swallow</code> and the file <code>src/HolyProject/Swallow.hs</code>. And we are ready to make our own real world unit test. We will first test the module <code>HolyProject.GithubAPI</code>. Lets create a file <code>test/HolyProject/GithubAPI/Test.hs</code> with the following content:</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb44-1" title="1"><span class="kw">module</span> <span class="dt">HolyProject.GithubAPI.Test</span></a>
<a class="sourceLine" id="cb44-2" title="2">( githubAPISuite</a>
<a class="sourceLine" id="cb44-3" title="3">) <span class="kw">where</span></a>
<a class="sourceLine" id="cb44-4" title="4"><span class="kw">import</span> <span class="dt">Test.Tasty</span> (testGroup, <span class="dt">TestTree</span>)</a>
<a class="sourceLine" id="cb44-5" title="5"><span class="kw">import</span> <span class="dt">Test.Tasty.HUnit</span></a>
<a class="sourceLine" id="cb44-6" title="6"><span class="kw">import</span> <span class="dt">HolyProject.GithubAPI</span></a>
<a class="sourceLine" id="cb44-7" title="7"></a>
<a class="sourceLine" id="cb44-8" title="8"><span class="ot">githubAPISuite ::</span> <span class="dt">TestTree</span></a>
<a class="sourceLine" id="cb44-9" title="9">githubAPISuite <span class="ot">=</span> testGroup <span class="st">&quot;GithubAPI&quot;</span></a>
<a class="sourceLine" id="cb44-10" title="10"> [ testCase <span class="st">&quot;Yann&quot;</span> <span class="op">$</span> ioTestEq</a>
<a class="sourceLine" id="cb44-11" title="11"> (searchGHUser <span class="st">&quot;Yann.Esposito@gmail.com&quot;</span>)</a>
<a class="sourceLine" id="cb44-12" title="12"> (<span class="dt">Just</span> <span class="st">&quot;\&quot;yogsototh\&quot;&quot;</span>)</a>
<a class="sourceLine" id="cb44-13" title="13"> , testCase <span class="st">&quot;Jasper&quot;</span> <span class="op">$</span> ioTestEq</a>
<a class="sourceLine" id="cb44-14" title="14"> (searchGHUser <span class="st">&quot;Jasper Van der Jeugt&quot;</span>)</a>
<a class="sourceLine" id="cb44-15" title="15"> (<span class="dt">Just</span> <span class="st">&quot;\&quot;jaspervdj\&quot;&quot;</span>)</a>
<a class="sourceLine" id="cb44-16" title="16"> ]</a>
<a class="sourceLine" id="cb44-17" title="17"></a>
<a class="sourceLine" id="cb44-18" title="18"><span class="co">-- | Test if some IO action returns some expected value</span></a>
<a class="sourceLine" id="cb44-19" title="19"><span class="ot">ioTestEq ::</span> (<span class="dt">Eq</span> a, <span class="dt">Show</span> a) <span class="ot">=&gt;</span> <span class="dt">IO</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Assertion</span></a>
<a class="sourceLine" id="cb44-20" title="20">ioTestEq action expected <span class="ot">=</span> action <span class="op">&gt;&gt;=</span> assertEqual <span class="st">&quot;&quot;</span> expected</a></code></pre></div>
<p>You have to modify your cabal file. More precisely, you have to add <code>HolyProject.GithubAPI</code> in the exposed modules of the library secion). You also have to update the <code>test/Test.hs</code> file to use <code>GithubAPI</code> instead of <code>Swallow</code>.</p>
<p>So we have our example of unit testing using IO. We search the github nickname for some people I know and we verify github continue to give the same answer as expected.</p>
<h4 id="property-testing-with-smallcheck-and-quickcheck">Property Testing with SmallCheck and QuickCheck</h4>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/zoot.jpg" alt="My name is Zoot. Just Zoot"/>
</div>
<p>When it comes to pure code, a very good method is to use QuickCheck and SmallCheck. SmallCheck will verify all cases up to some depth about some property. While QuickCheck will verify some random cases.</p>
<p>As this kind of verification of property is mostly doable on pure code, we will test the <code>StringUtils</code> module.</p>
<p>So dont forget to declare <code>HolyProject.StringUtils</code> in the exposed modules in the library section of your cabal file. Remove all references to the <code>Coconut</code> module.</p>
<p>Modify the <code>test/Test.hs</code> to remove all references about <code>Coconut</code>. Create a <code>test/HolyProject/StringUtils/Test.hs</code> file containing:</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb45-1" title="1"><span class="kw">module</span> <span class="dt">HolyProject.StringUtils.Test</span></a>
<a class="sourceLine" id="cb45-2" title="2">( stringUtilsSuite</a>
<a class="sourceLine" id="cb45-3" title="3">) <span class="kw">where</span></a>
<a class="sourceLine" id="cb45-4" title="4"><span class="kw">import</span> <span class="dt">Test.Tasty</span> (testGroup, <span class="dt">TestTree</span>)</a>
<a class="sourceLine" id="cb45-5" title="5"><span class="kw">import</span> <span class="dt">Test.Tasty.SmallCheck</span> (forAll)</a>
<a class="sourceLine" id="cb45-6" title="6"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Test.Tasty.SmallCheck</span> <span class="kw">as</span> <span class="dt">SC</span></a>
<a class="sourceLine" id="cb45-7" title="7"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Test.Tasty.QuickCheck</span> <span class="kw">as</span> <span class="dt">QC</span></a>
<a class="sourceLine" id="cb45-8" title="8"><span class="kw">import</span> <span class="dt">Test.SmallCheck.Series</span> (<span class="dt">Serial</span>)</a>
<a class="sourceLine" id="cb45-9" title="9"><span class="kw">import</span> <span class="dt">HolyProject.StringUtils</span></a>
<a class="sourceLine" id="cb45-10" title="10"></a>
<a class="sourceLine" id="cb45-11" title="11"><span class="ot">stringUtilsSuite ::</span> <span class="dt">TestTree</span></a>
<a class="sourceLine" id="cb45-12" title="12">stringUtilsSuite <span class="ot">=</span> testGroup <span class="st">&quot;StringUtils&quot;</span></a>
<a class="sourceLine" id="cb45-13" title="13"> [ SC.testProperty <span class="st">&quot;SC projectNameFromString idempotent&quot;</span> <span class="op">$</span></a>
<a class="sourceLine" id="cb45-14" title="14"> idempotent projectNameFromString</a>
<a class="sourceLine" id="cb45-15" title="15"> , SC.testProperty <span class="st">&quot;SC capitalize idempotent&quot;</span> <span class="op">$</span></a>
<a class="sourceLine" id="cb45-16" title="16"> deeperIdempotent capitalize</a>
<a class="sourceLine" id="cb45-17" title="17"> , QC.testProperty <span class="st">&quot;QC projectNameFromString idempotent&quot;</span> <span class="op">$</span></a>
<a class="sourceLine" id="cb45-18" title="18"> idempotent capitalize</a>
<a class="sourceLine" id="cb45-19" title="19"> ]</a>
<a class="sourceLine" id="cb45-20" title="20"></a>
<a class="sourceLine" id="cb45-21" title="21">idempotent f <span class="ot">=</span> \s <span class="ot">-&gt;</span> f s <span class="op">==</span> f (f s)</a>
<a class="sourceLine" id="cb45-22" title="22"></a>
<a class="sourceLine" id="cb45-23" title="23"><span class="ot">deeperIdempotent ::</span> (<span class="dt">Eq</span> a, <span class="dt">Show</span> a, <span class="dt">Serial</span> m a) <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> <span class="dt">SC.Property</span> m</a>
<a class="sourceLine" id="cb45-24" title="24">deeperIdempotent f <span class="ot">=</span> forAll <span class="op">$</span> SC.changeDepth1 (<span class="op">+</span><span class="dv">1</span>) <span class="op">$</span> \s <span class="ot">-&gt;</span> f s <span class="op">==</span> f (f s)</a></code></pre></div>
<p>The result is here:</p>
<pre>
All Tests
StringUtils
SC projectNameFromString idempotent: <span class="green">OK</span>
206 tests completed
SC capitalize idempotent: <span class="green">OK</span>
1237 tests completed
QC projectNameFromString idempotent: <span class="red">FAIL</span>
*** Failed! Falsifiable (after 19 tests and 5 shrinks):
"a a"
Use --quickcheck-replay '18 913813783 2147483380' to reproduce.
GithubAPI
Yann: <span class="green">OK</span>
Jasper: <span class="green">OK</span>
<span class="red">1 out of 5 tests failed</span>
</pre>
<p>The test fail, but this is not an error. Our <code>capitalize</code> function shouldnt be idempotent. I simply added this test to show what occurs when a test fail. If you want to look more closely to the error you could do this:</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb46-1" title="1">$ <span class="ex">./interact</span></a>
<a class="sourceLine" id="cb46-2" title="2"><span class="ex">GHCi</span>, version 7.6.2: http://www.haskell.org/ghc/ :? for help</a>
<a class="sourceLine" id="cb46-3" title="3"><span class="ex">Loading</span> package ghc-prim ... linking ... done.</a>
<a class="sourceLine" id="cb46-4" title="4"><span class="ex">Loading</span> package integer-gmp ... linking ... done.</a>
<a class="sourceLine" id="cb46-5" title="5"><span class="ex">Loading</span> package base ... linking ... done.</a>
<a class="sourceLine" id="cb46-6" title="6"><span class="ex">Prelude</span><span class="op">&gt;</span> :l src/HolyProject/StringUtils</a>
<a class="sourceLine" id="cb46-7" title="7">[<span class="ex">1</span> of 1] Compiling HolyProject.StringUtils ( src/HolyProject/StringUtils.hs, interpreted )</a>
<a class="sourceLine" id="cb46-8" title="8"><span class="ex">Ok</span>, modules loaded: HolyProject.StringUtils.</a>
<a class="sourceLine" id="cb46-9" title="9"><span class="ex">*HolyProject.StringUtils</span><span class="op">&gt;</span> capitalize <span class="st">&quot;a a&quot;</span></a>
<a class="sourceLine" id="cb46-10" title="10"><span class="dt"><span class="highlight"></span><span class="st">&quot;AA&quot;</span><span class="dt"></span></span></a>
<a class="sourceLine" id="cb46-11" title="11"><span class="ex">*HolyProject.StringUtils</span><span class="op">&gt;</span> capitalize (capitalize <span class="st">&quot;a a&quot;</span>)</a>
<a class="sourceLine" id="cb46-12" title="12"><span class="dt"><span class="highlight"></span><span class="st">&quot;Aa&quot;</span><span class="dt"></span></span></a>
<a class="sourceLine" id="cb46-13" title="13"><span class="ex">*HolyProject.StringUtils</span><span class="op">&gt;</span></a></code></pre></div>
<p>It is important to use <code>./interact</code> instead of <code>ghci</code>. Because we need to tell <code>ghci</code> how to found the package installed.</p>
<p>Apparently, SmallCheck didnt found any counter example. I dont know how it generates Strings and using deeper search is really long.</p>
<h2 id="conclusion">Conclusion</h2>
<div>
<img src="/Scratch/img/blog/Holy-Haskell-Starter/a-blessing.jpg" alt="Rabbit"/>
</div>
<p>Congratulation!</p>
<p>Now you could start programming in Haskell and publish your own cabal package.</p>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>For example, you have to install the test libraries manually to use <code>cabal test</code>.<a href="#fnref1" class="footnote-back">↩</a></p></li>
<li id="fn2"><p>There is no easy way to do something like <code>name=$(ask name)</code>. Simply because <code>$(ask name)</code> run in another process which doesnt get access to the standard input<a href="#fnref2" class="footnote-back">↩</a></p></li>
<li id="fn3"><p>Having a good level of power in templates is very difficult. <span class="sc"><abbr title="In my Humble Opinion">imho</abbr></span> Mustache has made the best compromise.<a href="#fnref3" class="footnote-back">↩</a></p></li>
</ol>
</section>]]></summary>
</entry>
<entry>
<title>Parsec Presentation</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Parsec-Presentation/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Parsec-Presentation/index.html</id>
<published>2013-10-09T00:00:00Z</published>
<updated>2013-10-09T00:00:00Z</updated>
<summary type="html"><![CDATA[<p><img src="http://yogsototh.github.io/parsec-presentation/parsec/img/mp/AST.png" alt="AST" /><br />
</p>
<div class="intro">
<p><span class="sc"><abbr title="Trop long; pas lu">tlpl</abbr>: </span> Une introduction rapide à Parsec. Un parser en Haskell.</p>
</div>
<ul>
<li>The <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> presentation is <a href="http://yogsototh.github.io/parsec-presentation/parsec.html">here</a>.</li>
</ul>
<div style="display:none">
() () () () () (
) (
<p>) () () () () () () () () ()</p>
</div>
<!-- Begin slides. Just make elements with a class of slide. -->
<section class="slide">
<div style="text-align:center; font-size: .9em; width: 100%; line-height: 1.2em">
<h1 style="position: relative;">
Parsec
</h1>
<author><em class="base1">by</em> Yann Esposito</author>
<div style="font-size:.5em; margin: 0 1em;">
<p><twitter> <a href="http://twitter.com/yogsototh"><span class="citation" data-cites="yogsototh">@yogsototh</span></a>, </twitter> <googleplus> <a href="https://plus.google.com/117858550730178181663">+yogsototh</a> </googleplus></p>
</div>
<div style="font-size:.8em">
<p><em class="base1">for</em> <a href="http://www.meetup.com/riviera-scala-clojure"> Riviera Scala Clojure Meetup (Haskell) </a><br/> <em class="base1">the</em> <ti style="font-size: .8em">8 Oct 2013</ti></p>
</div>
</div>
</section>
<section class="slide">
<h2 id="parsing">
Parsing
</h2>
<p>
Latin pars (ōrātiōnis), meaning part (of speech).
</p>
<ul>
<li>
<strong>analysing a string of symbols</strong>
</li>
<li>
<strong>formal grammar</strong>.
</li>
</ul>
</section>
<section class="slide">
<h2 id="parsing-in-programming-languages">
Parsing in Programming Languages
</h2>
<p>
Complexity:
</p>
<table>
<thead>
<tr class="header">
<th align="left">
Method
</th>
<th align="left">
Typical Example
</th>
<th align="left">
Output Data Structure
</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="left">
Splitting
</td>
<td align="left">
CSV
</td>
<td align="left">
Array, Map
</td>
</tr>
<tr class="even">
<td align="left">
Regexp
</td>
<td align="left">
email
</td>
<td align="left">
<ul>
<li>Fixed Layout Tree
</td>
</tr>
<tr class="odd">
<td align="left">
Parser
</td>
<td align="left">
Programming language
</td>
<td align="left">
<ul>
<li>Most Data Structure
</td>
</tr>
</tbody>
</table>
</section>
<section class="slide">
<h2 id="parser-culture">
Parser <span class="and">&amp;</span> culture
</h2>
<p>
In Haskell Parser are really easy to use.
</p>
<p>
Generally:
</p>
<ul>
<li>
In most languages: <strong>split</strong> then <strong>regexp</strong> then <strong>parse</strong>
</li>
<li>
In Haskell: <strong>split</strong> then <strong>parse</strong>
</li>
</ul>
</section>
<section class="slide">
<h2 id="parsing-example">
Parsing Example
</h2>
<p>
From String:
</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell">(<span class="dv">1</span><span class="fu">+</span><span class="dv">3</span>)<span class="fu">*</span>(<span class="dv">1</span><span class="fu">+</span><span class="dv">5</span><span class="fu">+</span><span class="dv">9</span>)</code></pre>
<p>
To data structure:
</p>
<p>
<img src="http://yogsototh.github.io/parsec-presentation/parsec/img/mp/AST.png" alt="AST" /><br />
</p>
</section>
<section class="slide">
<h2 id="parsec">
Parsec
</h2>
<blockquote>
<p>
Parsec lets you construct parsers by combining high-order Combinators to create larger expressions.
</p>
<p>
Combinator parsers are written and used within the same programming language as the rest of the program.
</p>
<p>
The parsers are first-class citizens of the languages […]"
</p>
<p>
<em><a href="http://www.haskell.org/haskellwiki/Parsec">Haskell Wiki</a></em>
</p>
</blockquote>
</section>
<section class="slide">
<h2 id="parser-libraries">
Parser Libraries
</h2>
<p>
In reality there are many choices:
</p>
<table>
<tbody>
<tr class="odd">
<td align="left">
attoparsec
</td>
<td align="left">
fast
</td>
</tr>
<tr class="even">
<td align="left">
Bytestring-lexing
</td>
<td align="left">
fast
</td>
</tr>
<tr class="odd">
<td align="left">
Parsec 3
</td>
<td align="left">
powerful, nice error reporting
</td>
</tr>
</tbody>
</table>
</section>
<section class="slide">
<h2 id="haskell-remarks-1">
Haskell Remarks (1)
</h2>
<p>
spaces are meaningful
</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell">f x <span class="co">-- ⇔ f(x) in C-like languages</span>
f x y <span class="co">-- ⇔ f(x,y)</span></code></pre>
</section>
<section class="slide">
<h2 id="haskell-remarks-2">
Haskell Remarks (2)
</h2>
<p>
Dont mind strange operators (<code>&lt;*&gt;</code>, <code>&lt;$&gt;</code>).<br />Consider them like separators, typically commas.<br />They are just here to deal with types.
</p>
<p>
Informally:
</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell">toto <span class="fu">&lt;$&gt;</span> x <span class="fu">&lt;*&gt;</span> y <span class="fu">&lt;*&gt;</span> z
<span class="co">-- ⇔ toto x y z</span>
<span class="co">-- ⇔ toto(x,y,z) in C-like languages</span></code></pre>
</section>
<section class="slide">
<h2 id="minimal-parsec-examples">
Minimal Parsec Examples
</h2>
<pre class="sourceCode haskell"><code class="sourceCode haskell">whitespaces <span class="fu">=</span> many (oneOf <span class="st">&quot;\t &quot;</span>)
number <span class="fu">=</span> many1 digit
symbol <span class="fu">=</span> oneOf <span class="st">&quot;!#$%<span class="and">&amp;</span>|*+-/:&lt;=&gt;?@^_~&quot;</span></code></pre>
<pre class="sourceCode haskell">
<code class="sourceCode haskell"><span class="st">" \t "</span> <span class="co"> whitespaces on " \t "</span> <span class="st">""</span> <span class="co"> whitespaces on “32”</span> <span class="st">“32”</span> <span class="co"> number on “32”</span></li>
</ul></li>
</ul>
<span class="co"> number on " ]]></summary>
</entry>
<entry>
<title>Rational Web Framework Choice</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Rational-Web-Framework-Choice/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Rational-Web-Framework-Choice/index.html</id>
<published>2013-08-06T00:00:00Z</published>
<updated>2013-08-06T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Rational-Web-Framework-Choice/battle-of-lepanto-vicentino-andrea.jpg" alt="Main image"/>
</div>
<div class="intro">
<p><span class="sc"><abbr title="Trop long; pas lu">tlpl</abbr>: </span> Comment déterminer de la façon la plus rationnelle possible le meilleur framework work relativement à vos besoins. <a href="#the-result">Cliquez ici pour aller au résultats</a>. Cet article nest disponible quen anglais.</p>
</div>
<p>This is it.<br />
Youve got the next big idea.<br />
You just need to make a very simple web application.</p>
<p>It sounds easy! You just need to choose a good modern web framework, when suddenly:</p>
<figure>
<img src="/Scratch/img/blog/Rational-Web-Framework-Choice/choice_paralysis.gif" alt="[Choice Paralysis][choice_paralysis]"/>
<figcaption>
<a href="https://en.wikipedia.org/wiki/Analysis_paralysis">Choice Paralysis</a>
</figcaption>
</figure>
<p>After your brain stack overflowed, you decide to use a very simple methodology. Answer two questions:</p>
<p><strong>Which language am I familiar with?<br />
What is the most popular web framework for this language?</strong></p>
<p>Great! This is it.</p>
<p>But, you continually hear this little voice.</p>
<blockquote>
<p><strong>“You didnt made a bad choice, yes. But …<br />
you hadnt made the best either.”</strong></p>
</blockquote>
<p>This article try to determine in the most objective and rational way the best(s) web framework(s) depending on your needs. To reach this goal, I will provide a decision tool in the result section.</p>
<p>I will use the following methodology:</p>
<p><strong>Methodology</strong></p>
<ol type="1">
<li>Model how to make choice
<ol type="a">
<li>choose important parameters</li>
<li>organize (hierarchize) them</li>
<li>write down an objective chooser</li>
</ol></li>
<li>Grab objective quantified informations about web frameworks relatively to choosen parameters</li>
<li>Sanitize your data in order to handle imprecisions, lack of informations…</li>
<li>Apply the model of choice to your informations</li>
</ol>
<blockquote>
<p><strong>☞ Important Note</strong><br />
I am far from happy to the actual result. There are a lot of biases, for example in the choice of the parameters. The same can be said about the data I gathered. I am using very imprecise informations. But, as far as I know, this is the only article which use many different parameters to help you choose a web framework.</p>
<p>This is why I made a very flexible decision tool:</p>
<p><a href="#the-result">Decision tool</a>.</p>
</blockquote>
<h2 id="model">Model</h2>
<p>Here are the important features (properties/parameters) I selected to make the choice:</p>
<ol type="1">
<li><em><strong>Popularity</strong></em>, which correlate with:
<ul>
<li>number of tested libraries</li>
<li>facility to find learning material</li>
<li>ability to find another developer to work with</li>
</ul></li>
<li><em><strong>Efficiency</strong></em>, which is generally correlated to:
<ul>
<li>how much processing power youll need per user</li>
<li>maintenance price per user</li>
<li>how long the user will wait to see/update data</li>
</ul></li>
<li><em><strong>Expressiveness</strong></em>, which is generally correlated to:
<ul>
<li>faster development</li>
<li>flexibility, adaptability</li>
</ul></li>
<li><em><strong>Robustness</strong></em>, which correlate with:
<ul>
<li>security</li>
<li>fewer bugs</li>
</ul></li>
</ol>
<p>Each feature is quite important and mostly independant from each other. I tried to embrace most important topics concerning web frameworks with these four properties. I am fully concious some people might lack another important feature. Nonetheless the methodology used here can be easily replicated. If you lack an important property add it at will and use this choice method.</p>
<p>Also each feature is very hard to measure with precision. This is why we will only focus on order of magnitude.</p>
<p>For each property a framework could have one of the six possible values: Excellent, Very Good, Good, Medium, Bad or Very Bad</p>
<p>So how to make a decision model from these informations?</p>
<p>One of the most versatile method is to give a weight for each cluster value. And to select the framework maximizing this score:</p>
<pre><code>score(framework) = efficiency + robustness + expressiveness + popularity</code></pre>
<blockquote>
<p>For example:</p>
<table>
<tbody>
<tr class="odd">
<td>Expressiveness</td>
<td style="text-align: right;">10</td>
<td style="text-align: right;">7</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">-∞</td>
<td style="text-align: right;">-∞</td>
<td style="text-align: right;">-∞</td>
</tr>
<tr class="even">
<td>Popularity</td>
<td style="text-align: right;">5</td>
<td style="text-align: right;">5</td>
<td style="text-align: right;">4</td>
<td style="text-align: right;">3</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">1</td>
</tr>
<tr class="odd">
<td>Efficiency</td>
<td style="text-align: right;">10</td>
<td style="text-align: right;">8</td>
<td style="text-align: right;">6</td>
<td style="text-align: right;">4</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">1</td>
</tr>
<tr class="even">
<td>Robustness</td>
<td style="text-align: right;">10</td>
<td style="text-align: right;">8</td>
<td style="text-align: right;">6</td>
<td style="text-align: right;">4</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">1</td>
</tr>
</tbody>
</table>
<p>Using this weighted table, that means:</p>
<ul>
<li>we discard the three least expressive clusters.</li>
<li>We dont make any difference between excellent and very good in popularity.</li>
<li>Concerning efficient framework in excellent cluster will have 2 more points than the “very good” cluster.</li>
</ul>
<p>So for each framework we compute its score relatively to a weighted table. And we select the best(s).</p>
<p><strong>Example</strong>: Using this hypothetic framework and the preceeding table.</p>
<table>
<thead>
<tr class="header">
<th></th>
<th>Expressiveness</th>
<th>Popularity</th>
<th>Efficiency</th>
<th>Robustness</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>yog</td>
<td>Excellent</td>
<td>Very Bad</td>
<td>Medium</td>
<td>Very Good</td>
</tr>
</tbody>
</table>
<pre><code>score(yog) = 10 + 0 + 4 + 8 = 22</code></pre>
</blockquote>
<p>Most needs should be expressed by such a weighted table. In the result section, we will discuss this further.</p>
<p>It is now time to try to get these measures.</p>
<h2 id="objective-measures">Objective measures</h2>
<p>None of the four properties I choosen can be measured with perfect precision. But we could get the order of magnitude for each.</p>
<p>I tried to focus on the framework only. But it is often easier to start by studying the language first.</p>
<p>For example, I have datas about popularity by language and I also have different datas concerning popularity by framework. Even if I use only the framework focused datas in my final decision model, it seemed important to me to discuss about the datas for the languages. The goal is to provide a tool to help decision not to give a decision for you.</p>
<h3 id="popularity">Popularity</h3>
<p><a href="http://redmonk.com/sogrady/2013/02/28/language-rankings-1-13/">RedMonk Programming Language Rankings (January 2013)</a> provide an apparent good measure of popularity. While not perfect the current measure feel mostly right. They create an image using stack overflow and github data. Vertical correspond to the number of questions on stackoverflow. Horizontal correspond to the number of projects on github.</p>
<p>If you look at the image, your eye can see about four clusters. The 1<sup>st</sup> cluster correspond to mainstream languages:</p>
<figure>
<img src="/Scratch/img/blog/Rational-Web-Framework-Choice/mainstreamlanguages.png" alt="Mainstream Languages Cluster from [RedMonk][redmonk]"/>
<figcaption>
Mainstream Languages Cluster from <a href="http://redmonk.com/sogrady/2013/02/28/language-rankings-1-13/">RedMonk</a>
</figcaption>
</figure>
<p>Most developer know at least one of these language.</p>
<p>The second cluster is quite bigger. It seems to correspond to languages with a solid community behind them.</p>
<figure>
<img src="/Scratch/img/blog/Rational-Web-Framework-Choice/secondtierlanguages.png" alt="Second tier languages from [RedMonk][redmonk]"/>
<figcaption>
Second tier languages from <a href="http://redmonk.com/sogrady/2013/02/28/language-rankings-1-13/">RedMonk</a>
</figcaption>
</figure>
<p>I dont get into detail, but you could also see third and fourth tier popular languages.</p>
<p>So:</p>
<p><strong>Mainstream</strong>: JavaScript, Java, PHP, Python, Ruby, <code>C#</code>, <code>C++</code>, <code>C</code>, Objective-C, Perl, Shell</p>
<p><strong>Good</strong>: Scala, Haskell, Visual Basic, Assembly, R, Matlab, ASP, ActionScript, Coffeescript, Groovy, Clojure, Lua, Prolog</p>
<p><strong>Medium</strong>: Erlang, Go, Delphi, D, Racket, Scheme, ColdFusion, F#, FORTRAN, Arduino, Tcl, Ocaml</p>
<p><strong>Bad</strong>: third tier <strong>Very Bad</strong>: fourth tier</p>
<p>I dont thing I could find easily web frameworks for third or fourth tier languages.</p>
<p>For now, I only talked about language popularity. But what about framework popularity? I made a test using number of question on stackoverflow only. Then by dividing by two for each 6 cluster:</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Cluster</th>
<th style="text-align: left;">Language</th>
<th style="text-align: left;">Framework</th>
<th style="text-align: right;">#nb</th>
<th style="text-align: right;">%</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Excellent</td>
<td style="text-align: left;">Ruby</td>
<td style="text-align: left;">Rails</td>
<td style="text-align: right;">176208</td>
<td style="text-align: right;">100%</td>
</tr>
<tr class="even">
<td style="text-align: left;">Very Good</td>
<td style="text-align: left;">Python</td>
<td style="text-align: left;">Django</td>
<td style="text-align: right;">57385</td>
<td style="text-align: right;">&lt;50%</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Servlet</td>
<td style="text-align: right;">54139</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Spring</td>
<td style="text-align: right;">31641</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Node.js</td>
<td style="text-align: left;">node.js</td>
<td style="text-align: right;">27243</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Codeigniter</td>
<td style="text-align: right;">21503</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Groovy</td>
<td style="text-align: left;">Grails</td>
<td style="text-align: right;">20222</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;">Good</td>
<td style="text-align: left;">Ruby</td>
<td style="text-align: left;">Sinatra</td>
<td style="text-align: right;">8631</td>
<td style="text-align: right;">&lt;25%</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Python</td>
<td style="text-align: left;">Flask</td>
<td style="text-align: right;">7062</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Laravel</td>
<td style="text-align: right;">6982</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Kohana</td>
<td style="text-align: right;">5959</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Node.js</td>
<td style="text-align: left;">Express</td>
<td style="text-align: right;">5009</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;">Medium</td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Cake</td>
<td style="text-align: right;">4554</td>
<td style="text-align: right;">&lt;13%</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C♯</td>
<td style="text-align: left;">ServiceStack</td>
<td style="text-align: right;">3838</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Scala</td>
<td style="text-align: left;">Play</td>
<td style="text-align: right;">3823</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Wicket</td>
<td style="text-align: right;">3819</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Dart</td>
<td style="text-align: left;">Dart</td>
<td style="text-align: right;">3753</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Slim</td>
<td style="text-align: right;">3361</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Python</td>
<td style="text-align: left;">Tornado</td>
<td style="text-align: right;">3321</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Scala</td>
<td style="text-align: left;">Lift</td>
<td style="text-align: right;">2844</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">Go</td>
<td style="text-align: right;">2689</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;">Bad</td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Tapestry</td>
<td style="text-align: right;">1197</td>
<td style="text-align: right;">&lt;6%</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C♯</td>
<td style="text-align: left;">aspnet</td>
<td style="text-align: right;">1000</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Haskell</td>
<td style="text-align: left;">Yesod</td>
<td style="text-align: right;">889</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Silex</td>
<td style="text-align: right;">750</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Lithium</td>
<td style="text-align: right;">732</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C♯</td>
<td style="text-align: left;">nancy</td>
<td style="text-align: right;">705</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;">Very bad</td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Grizzly</td>
<td style="text-align: right;">622</td>
<td style="text-align: right;">&lt;3%</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Erlang</td>
<td style="text-align: left;">Cowboy</td>
<td style="text-align: right;">568</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Perl</td>
<td style="text-align: left;">Dancer</td>
<td style="text-align: right;">496</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Symphony2</td>
<td style="text-align: right;">491</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">Revel</td>
<td style="text-align: right;">459</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clojure</td>
<td style="text-align: left;">Compojure</td>
<td style="text-align: right;">391</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Perl</td>
<td style="text-align: left;">Mojolicious</td>
<td style="text-align: right;">376</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Scala</td>
<td style="text-align: left;">Scalatra</td>
<td style="text-align: right;">349</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Scala</td>
<td style="text-align: left;">Finagle</td>
<td style="text-align: right;">336</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Phalcon</td>
<td style="text-align: right;">299</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">js</td>
<td style="text-align: left;">Ringo</td>
<td style="text-align: right;">299</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Gemini</td>
<td style="text-align: right;">276</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Haskell</td>
<td style="text-align: left;">Snap</td>
<td style="text-align: right;">263</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Perl</td>
<td style="text-align: left;">Plack</td>
<td style="text-align: right;">257</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Erlang</td>
<td style="text-align: left;">Elli</td>
<td style="text-align: right;">230</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Dropwizard</td>
<td style="text-align: right;">188</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Yaf</td>
<td style="text-align: right;">146</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Play1</td>
<td style="text-align: right;">133</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Node.js</td>
<td style="text-align: left;">Hapi</td>
<td style="text-align: right;">131</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Java</td>
<td style="text-align: left;">Vertx</td>
<td style="text-align: right;">60</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Scala</td>
<td style="text-align: left;">Unfiltered</td>
<td style="text-align: right;">42</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C</td>
<td style="text-align: left;">onion</td>
<td style="text-align: right;">18</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clojure</td>
<td style="text-align: left;">http-kit</td>
<td style="text-align: right;">17</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Perl</td>
<td style="text-align: left;">Kelp</td>
<td style="text-align: right;">16</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Micromvc</td>
<td style="text-align: right;">13</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Lua</td>
<td style="text-align: left;">Openresty</td>
<td style="text-align: right;">8</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C++</td>
<td style="text-align: left;">cpoll-cppsp</td>
<td style="text-align: right;">5</td>
<td style="text-align: right;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clojure</td>
<td style="text-align: left;">Luminus</td>
<td style="text-align: right;">3</td>
<td style="text-align: right;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">Phreeze</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;"></td>
</tr>
</tbody>
</table>
<p>As we can see, our framework popularity indicator can be quite different from its language popularity. For now I didnt found a nice way to merge the results from RedMonk with these one. So Ill use these unperfect one. Hopefully the order of magninute is mostly correct for most framework.</p>
<h3 id="efficiency">Efficiency</h3>
<p>Another objective measure is efficiency. We all know benchmarks are all flawed. But they are the only indicators concerning efficiency we have.</p>
<p>I used the benchmark from <a href="http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&amp;lang=all&amp;data=u64q">benchmarksgame</a>. Mainly, there are five clusters:</p>
<table>
<tbody>
<tr class="odd">
<td style="text-align: left;">1x→2x</td>
<td style="text-align: left;"><code>C</code>, <code>C++</code></td>
</tr>
<tr class="even">
<td style="text-align: left;">2x→3x</td>
<td style="text-align: left;">Java 7, Scala, OCamL, Haskell, Go, Common LISP</td>
</tr>
<tr class="odd">
<td style="text-align: left;">3x→10x</td>
<td style="text-align: left;">C♯, Clojure, Racket, Dart</td>
</tr>
<tr class="even">
<td style="text-align: left;">10x→30x</td>
<td style="text-align: left;">Erlang</td>
</tr>
<tr class="odd">
<td style="text-align: left;">30x→</td>
<td style="text-align: left;">PHP, Python, Perl, Ruby, JRuby</td>
</tr>
</tbody>
</table>
<p>Remarks concerning some very slow languages:</p>
<ul>
<li>PHP ; huge variations, can be about 1.5x C speed in best case.</li>
<li>Python ; huge variations, can be about 1.5x C speed in best case</li>
<li>Perl ; Can be about 3x C speed in best case</li>
<li>Ruby, JRuby ; mostly very slow.</li>
</ul>
<p>This is a first approach. The speed of the language for basic benchmarks. But, here we are interrested in web programming. Fortunately techempower has made some tests focused on most web frameworks:</p>
<p><a href="http://www.techempower.com/blog/2013/07/02/frameworks-round-6/">Web framework benchmarks</a>.</p>
<p>These benchmark doesnt fit well with our needs. The values are certainly quite imprecise to your real usage. The goal is just to get an order of magnitude for each framework. Another problem is the high number of informations.</p>
<p>As always, we should remember these informations are also imprecise. So I simply made some classes of efficiency.</p>
<p>Remark: I separated the clusters by using power of 2 relatively to the fastest.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Cluster</th>
<th style="text-align: left;">Language</th>
<th style="text-align: left;">Framework</th>
<th style="text-align: center;">#nb</th>
<th style="text-align: left;">slowness</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Excellent</td>
<td style="text-align: left;">C++</td>
<td style="text-align: left;">cpoll-cppsp</td>
<td style="text-align: center;">114,711</td>
<td style="text-align: left;">1×</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">gemini</td>
<td style="text-align: center;">105,204</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Lua</td>
<td style="text-align: left;">openresty</td>
<td style="text-align: center;">93,882</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">servlet</td>
<td style="text-align: center;">90,580</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C++</td>
<td style="text-align: left;">cpoll-pool</td>
<td style="text-align: center;">89,167</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">go</td>
<td style="text-align: center;">76,024</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">finagle</td>
<td style="text-align: center;">68,413</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">revel</td>
<td style="text-align: center;">66,990</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">rest-express</td>
<td style="text-align: center;">63,209</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;">Very Good</td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">wicket</td>
<td style="text-align: center;">48,772</td>
<td style="text-align: left;">&gt;2×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">scalatra</td>
<td style="text-align: center;">48,594</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">http-kit</td>
<td style="text-align: center;">42,703</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">spring</td>
<td style="text-align: center;">36,643</td>
<td style="text-align: left;">&gt;3×</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">php</td>
<td style="text-align: center;">36,605</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">tapestry</td>
<td style="text-align: center;">35,032</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">compojure</td>
<td style="text-align: center;">32,088</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">ringo</td>
<td style="text-align: center;">31,962</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">dropwizard</td>
<td style="text-align: center;">31,514</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">luminus</td>
<td style="text-align: center;">30,672</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;">Good</td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">play-slick</td>
<td style="text-align: center;">29,950</td>
<td style="text-align: left;">&gt;4×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">unfiltered</td>
<td style="text-align: center;">29,782</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Erl</td>
<td style="text-align: left;">elli</td>
<td style="text-align: center;">28,862</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">vertx</td>
<td style="text-align: center;">28,075</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">nodejs</td>
<td style="text-align: center;">27,598</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Erl</td>
<td style="text-align: left;">cowboy</td>
<td style="text-align: center;">24,669</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C</td>
<td style="text-align: left;">onion</td>
<td style="text-align: center;">23,649</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Hkl</td>
<td style="text-align: left;">yesod</td>
<td style="text-align: center;">23,304</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">express</td>
<td style="text-align: center;">22,856</td>
<td style="text-align: left;">&gt;5×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">play-scala</td>
<td style="text-align: center;">22,372</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav g</td>
<td style="text-align: left;">rizzly-jersey</td>
<td style="text-align: center;">20,550</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">tornado</td>
<td style="text-align: center;">20,372</td>
<td style="text-align: left;">&gt;6×</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">phalcon</td>
<td style="text-align: center;">18,481</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Grv</td>
<td style="text-align: left;">grails</td>
<td style="text-align: center;">18,467</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">plack</td>
<td style="text-align: center;">16,647</td>
<td style="text-align: left;">&gt;7×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">yaf</td>
<td style="text-align: center;">14,388</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;">Medium</td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">hapi</td>
<td style="text-align: center;">11,235</td>
<td style="text-align: left;">&gt;10×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play1</td>
<td style="text-align: center;">9,979</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Hkl</td>
<td style="text-align: left;">snap</td>
<td style="text-align: center;">9,196</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">kelp</td>
<td style="text-align: center;">8,250</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">flask</td>
<td style="text-align: center;">8,167</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play-java</td>
<td style="text-align: center;">7,905</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav p</td>
<td style="text-align: left;">lay-java-jpa</td>
<td style="text-align: center;">7,846</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">micromvc</td>
<td style="text-align: center;">7,387</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">dancer</td>
<td style="text-align: center;">5,040</td>
<td style="text-align: left;">&gt;20×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">mojolicious</td>
<td style="text-align: center;">4,371</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">ringo-conv</td>
<td style="text-align: center;">4,249</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">django</td>
<td style="text-align: center;">4,026</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">codeigniter</td>
<td style="text-align: center;">3,809</td>
<td style="text-align: left;">&gt;30×</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Bad</td>
<td style="text-align: left;">Rby</td>
<td style="text-align: left;">rails</td>
<td style="text-align: center;">3,445</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">lift</td>
<td style="text-align: center;">3,311</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">slim</td>
<td style="text-align: center;">3,112</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">kohana</td>
<td style="text-align: center;">2,378</td>
<td style="text-align: left;">&gt;40×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">silex</td>
<td style="text-align: center;">2,364</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;">Very Bad</td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">laravel</td>
<td style="text-align: center;">1,639</td>
<td style="text-align: left;">&gt;60×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">phreeze</td>
<td style="text-align: center;">1,410</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">lithium</td>
<td style="text-align: center;">1,410</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">fuel</td>
<td style="text-align: center;">1,410</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">cake</td>
<td style="text-align: center;">1,287</td>
<td style="text-align: left;">&gt;80×</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">symfony2</td>
<td style="text-align: center;">879</td>
<td style="text-align: left;">&gt;100×</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">aspnet-mvc</td>
<td style="text-align: center;">871</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Rby</td>
<td style="text-align: left;">sinatra</td>
<td style="text-align: center;">561</td>
<td style="text-align: left;">&gt;200×</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">servicestack</td>
<td style="text-align: center;">51</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Dar</td>
<td style="text-align: left;">dart</td>
<td style="text-align: center;">0</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">nancy</td>
<td style="text-align: center;">0</td>
<td style="text-align: left;"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">web-simple</td>
<td style="text-align: center;">0</td>
<td style="text-align: left;"></td>
</tr>
</tbody>
</table>
<p>These are manually made clusters. But you get the idea. Certainly, some framework could jump between two different clusters. So this is something to remember. But as always, the order of magnitude is certainly mostly right.</p>
<h1 id="expressiveness">Expressiveness</h1>
<p>Now, how to objectively measure expressiveness?</p>
<p>RedMonk had a very good idea to find an objective (while imprecise) measure of each language expressiveness. Read this <a href="http://redmonk.com/dberkholz/2013/03/25/programming-languages-ranked-by-expressiveness/">article</a> for details.</p>
<p>After filtering languages suitable for web development, we end up with some clusters:</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Cluster</th>
<th style="text-align: left;">Languages</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Excellent</td>
<td style="text-align: left;">Coffeescript, Clojure, Haskell</td>
</tr>
<tr class="even">
<td style="text-align: left;">Very Good</td>
<td style="text-align: left;">Racket, Groovy, R, Scala, OCamL, F♯, Erlang, Lisp, Go</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Medium</td>
<td style="text-align: left;">Perl, Python, Objective-C, Scheme, Tcl, Ruby</td>
</tr>
<tr class="even">
<td style="text-align: left;">Bad</td>
<td style="text-align: left;">Lua, Fortran (free-format), PHP, Java, C++, C♯</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Very Bad</td>
<td style="text-align: left;">Assembly, C, Javascript,</td>
</tr>
</tbody>
</table>
<p>Unfortunately there is no information about dart. So I simply give a very fast look at the syntax. As it looked a lot like javascript and js is quite low. I decided to put it close to java.</p>
<p>Also an important remark, javascript score very badly here while coffeescript (compiling to js) score “excellent”. So if you intend to use a javascript framework but only with coffescript that should change substantially the score. As I dont believe it is the standard. Javascript oriented framework score very badly regarding expressiveness.</p>
<div id="toggle-expressiveness-table" class="button">
<span>Click here to show/hide the table for frameworks</span>
</div>
<div id="expressiveness-table">
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Cluster</th>
<th style="text-align: left;">Language</th>
<th style="text-align: left;">Framework</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Excellent</td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">luminus</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">http-kit</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">compojure</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Hkl</td>
<td style="text-align: left;">snap</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Hkl</td>
<td style="text-align: left;">yesod</td>
</tr>
<tr class="even">
<td style="text-align: left;">Very Good</td>
<td style="text-align: left;">Erl</td>
<td style="text-align: left;">elli</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Erl</td>
<td style="text-align: left;">cowboy</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">go</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">revel</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Grv</td>
<td style="text-align: left;">grails</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">lift</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">finagle</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">scalatra</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">play-scala</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">play-slick</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">unfiltered</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Medium</td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">kelp</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">plack</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">dancer</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">web-simple</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">mojolicious</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">flask</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">django</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">tornado</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Rby</td>
<td style="text-align: left;">rails</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Rby</td>
<td style="text-align: left;">sinatra</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Bad</td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">nancy</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">aspnet-mvc</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">servicestack</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C++</td>
<td style="text-align: left;">cpoll-pool</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C++</td>
<td style="text-align: left;">cpoll-cppsp</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Dar</td>
<td style="text-align: left;">dart</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play1</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">vertx</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">gemini</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">spring</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">wicket</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">servlet</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">tapestry</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play-java</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">dropwizard</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">rest-express</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play-java-jpa</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">grizzly-jersey</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Lua</td>
<td style="text-align: left;">openresty</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">php</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">yaf</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">cake</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">fuel</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">slim</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">silex</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">kohana</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">laravel</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">lithium</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">phalcon</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">phreeze</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">micromvc</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">symfony2</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">codeigniter</td>
</tr>
<tr class="even">
<td style="text-align: left;">Very Bad</td>
<td style="text-align: left;">C</td>
<td style="text-align: left;">onion</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">hapi</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">ringo</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">nodejs</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">express</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">ringo-conv</td>
</tr>
</tbody>
</table>
</div>
<h3 id="robustness">Robustness</h3>
<p>I couldnt find any complete study to give the number of bug relatively to each framework/language.</p>
<p>But one thing I saw from experience is the more powerful the type system the safest your application is. While the type system doesnt remove completely the need to test your application a very good type system tend to remove complete classes of bug.</p>
<p>Typically, not using pointer help to reduce the number of bugs due to bad references. Also, using a garbage collector, reduce greatly the probability to access unallocated space.</p>
<figure>
<img src="/Scratch/img/blog/Rational-Web-Framework-Choice/languagesafety.png" alt="Static Type Properties from [James IRY Blog][typesanalysis]"/>
<figcaption>
Static Type Properties from <a href="http://james-iry.blogspot.fr/2010/05/types-la-chart.html">James IRY Blog</a>
</figcaption>
</figure>
<p>From my point of view, robustness is mostly identical to safety.</p>
<p>Here are the clusters:</p>
<table>
<tbody>
<tr class="odd">
<td style="text-align: left;">Excellent</td>
<td>Haskell, Scheme, Erlang</td>
</tr>
<tr class="even">
<td style="text-align: left;">Very Good</td>
<td>Scala, Java, Clojure</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Good</td>
<td>Ruby, Python, Groovy, javascript, PHP</td>
</tr>
<tr class="even">
<td style="text-align: left;">Medium</td>
<td>C++, C#, Perl, Objective-C, Go, C</td>
</tr>
</tbody>
</table>
<p>So applying this to frameworks gives the following clusters:</p>
<div id="toggle-robustness-table" class="button">
<span>Click here to show/hide the table for frameworks</span>
</div>
<div id="robustness-table">
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Cluster</th>
<th style="text-align: left;">Language</th>
<th style="text-align: left;">Framework</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Excellent</td>
<td style="text-align: left;">Erl</td>
<td style="text-align: left;">elli</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Erl</td>
<td style="text-align: left;">cowboy</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Hkl</td>
<td style="text-align: left;">snap</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Hkl</td>
<td style="text-align: left;">yesod</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Very Good</td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">luminus</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">http-kit</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Clj</td>
<td style="text-align: left;">compojure</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play1</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">vertx</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">gemini</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">spring</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">wicket</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">servlet</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">tapestry</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play-java</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">dropwizard</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">rest-express</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">play-java-jpa</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Jav</td>
<td style="text-align: left;">grizzly-jersey</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">lift</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">finagle</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">scalatra</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">play-scala</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">play-slick</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Sca</td>
<td style="text-align: left;">unfiltered</td>
</tr>
<tr class="even">
<td style="text-align: left;">Good</td>
<td style="text-align: left;">Grv</td>
<td style="text-align: left;">grails</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">hapi</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">ringo</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">nodejs</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">express</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">JS</td>
<td style="text-align: left;">ringo-conv</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Lua</td>
<td style="text-align: left;">openresty</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">php</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">yaf</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">cake</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">fuel</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">slim</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">silex</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">kohana</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">laravel</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">lithium</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">phalcon</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">phreeze</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">micromvc</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">symfony2</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">PHP</td>
<td style="text-align: left;">codeigniter</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">flask</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">django</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Py</td>
<td style="text-align: left;">tornado</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Rby</td>
<td style="text-align: left;">rails</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Rby</td>
<td style="text-align: left;">sinatra</td>
</tr>
<tr class="even">
<td style="text-align: left;">Medium</td>
<td style="text-align: left;">C</td>
<td style="text-align: left;">onion</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">nancy</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">aspnet-mvc</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C#</td>
<td style="text-align: left;">servicestack</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">C++</td>
<td style="text-align: left;">cpoll-pool</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">C++</td>
<td style="text-align: left;">cpoll-cppsp</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Dar</td>
<td style="text-align: left;">dart</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">go</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Go</td>
<td style="text-align: left;">revel</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">kelp</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">plack</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">dancer</td>
</tr>
<tr class="even">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">web-simple</td>
</tr>
<tr class="odd">
<td style="text-align: left;"></td>
<td style="text-align: left;">Prl</td>
<td style="text-align: left;">mojolicious</td>
</tr>
</tbody>
</table>
</div>
<h2 id="the-result">The result</h2>
<p>For the result I initialized the table with my own needs.</p>
<p>And I am quite happy it confirms my current choice. I sware I didnt given yesod any bonus point. I tried to be the most objective and factual as possible.</p>
<p>Now, it is up to you to enter your preferences.</p>
<p>On each line you could change how important a feature is for you. From essential to unsignificant. Of course you could change the matrix at will.</p>
<p>I just show a top 10 frameworks. In order to give a more understandable measure I provide the log of the score.</p>
<table id="choice-matrix">
<tr>
<th>
</th>
<th>
Excellent
</th>
<th>
Very good
</th>
<th>
Good
</th>
<th>
Medium
</th>
<th>
Bad
</th>
<th>
Very bad
</th>
<th>
Importance
</th>
</tr>
<tr id="t-expressiveness">
<th>
Expressiveness
</th>
</tr>
<tr id="t-popularity">
<th>
Popularity
</th>
</tr>
<tr id="t-efficiency">
<th>
Efficiency
</th>
</tr>
<tr id="t-robustness">
<th>
Robustness
</th>
</tr>
</table>
<div id="compute" class="button">
<span>Click to force refresh</span>
</div>
<div id="result">
</div>
<script>// <![CDATA[ // <![CDATA[
function lt(x,y){return (x < y);}
function bal(balname,str){return '<'+balname+'>'+str+'</'+balname+'>';}
function ret(){return '<br/>';}
// ]]&gt; // ]]&gt;</script>
<script>// <![CDATA[
String.prototype.repeat = function(num){return new Array(num+1).join(this);};
(function(){function run(){if (window.$){
var languageOf={};
languageOf["elli"]="Erlang";
languageOf["cowboy"]="Erlang";
languageOf["snap"]="Haskell";
languageOf["yesod"]="Haskell";
languageOf["luminus"]="Clojure";
languageOf["http-kit"]="Clojure";
languageOf["compojure"]="Clojure";
languageOf["play1"]="Java";
languageOf["vertx"]="Java";
languageOf["gemini"]="Java";
languageOf["spring"]="Java";
languageOf["wicket"]="Java";
languageOf["servlet"]="Java";
languageOf["tapestry"]="Java";
languageOf["play-java"]="Java";
languageOf["dropwizard"]="Java";
languageOf["rest-express"]="Java";
languageOf["play-java-jpa"]="Java";
languageOf["grizzly-jersey"]="Java";
languageOf["lift"]="Scala";
languageOf["finagle"]="Scala";
languageOf["scalatra"]="Scala";
languageOf["play-scala"]="Scala";
languageOf["play-slick"]="Scala";
languageOf["unfiltered"]="Scala";
languageOf["grails"]="Groovy";
languageOf["hapi"]="javascript";
languageOf["ringo"]="javascript";
languageOf["nodejs"]="javascript";
languageOf["express"]="javascript";
languageOf["ringo-conv"]="javascript";
languageOf["openresty"]="Lua";
languageOf["php"]="PHP";
languageOf["yaf"]="PHP";
languageOf["cake"]="PHP";
languageOf["fuel"]="PHP";
languageOf["slim"]="PHP";
languageOf["silex"]="PHP";
languageOf["kohana"]="PHP";
languageOf["laravel"]="PHP";
languageOf["lithium"]="PHP";
languageOf["phalcon"]="PHP";
languageOf["phreeze"]="PHP";
languageOf["micromvc"]="PHP";
languageOf["symfony2"]="PHP";
languageOf["codeigniter"]="PHP";
languageOf["flask"]="Python";
languageOf["django"]="Python";
languageOf["tornado"]="Python";
languageOf["rails"]="Ruby";
languageOf["sinatra"]="Ruby";
languageOf["onion"]="C";
languageOf["nancy"]="C#";
languageOf["aspnet-mvc"]="C#";
languageOf["servicestack"]="C#";
languageOf["cpoll-pool"]="C++";
languageOf["cpoll-cppsp"]="C++";
languageOf["dart"]="Dart";
languageOf["go"]=" Go";
languageOf["revel"]=" Go";
languageOf["kelp"]="Perl";
languageOf["plack"]="Perl";
languageOf["dancer"]="Perl";
languageOf["web-simple"]="Perl";
languageOf["mojolicious"]="Perl";
popularityClusters=[[ "rails", "php"
],[ "django" , "servlet" , "spring" , "nodejs" , "codeigniter" , "grails"
],[ "sinatra" , "flask" , "laravel" , "kohana" , "rest-express", "express"
],[ "cake" , "servicestack" , "play-java", "play-slick"
, "wicket" , "dart" , "slim" , "tornado" , "lift" , "go"
],[ "tapestry" , "aspnet-mvc" , "yesod" , "silex" , "lithium" , "nancy"
],[ "grizzly" , "cowboy" , "dancer" , "symfony2" , "revel"
, "compojure" , "mojolicious" , "scalatra" , "finagle" , "phalcon"
, "ringo" , "gemini" , "snap" , "plack" , "elli" , "dropwizard"
, "yaf" , "play1" , "hapi" , "vertx" , "unfiltered" , "onion"
, "http-kit" , "kelp" , "micromvc" , "openresty" , "cpoll-pool"
, "cpoll-cppsp" , "luminus" , "phreeze"
]];
efficiencyClusters=[[ "cpoll-cppsp" , "gemini" , "openresty" , "servlet"
, "cpoll-pool" , "go" , "finagle" , "revel" , "rest-express"
],[ "wicket" , "scalatra" , "http-kit" , "spring" , "php" , "tapestry"
, "compojure" , "ringo" , "dropwizard" , "luminus"
],[ "play-slick" , "unfiltered" , "elli" , "vertx" , "nodejs" , "cowboy"
, "onion" , "yesod" , "express" , "play-scala" , "grizzly"
, "tornado" , "phalcon" , "grails" , "plack" , "yaf"
],[ "hapi" , "play1" , "snap" , "kelp" , "flask" , "play-java"
, "play-java-jpa" , "micromvc" , "dancer" , "mojolicious" , "ringo-conv"
, "django" , "codeigniter"
],[ "rails" , "lift" , "slim" , "kohana" , "silex"
],[ "laravel" , "phreeze" , "lithium" , "fuel" , "cake" , "symfony2"
, "aspnet-mvc" , "sinatra" , "servicestack" , "dart" , "nancy" , "web-simple"
]];
expressivenessClusters=[[
"luminus" , "http-kit" , "compojure" , "snap" , "yesod"
],[ "elli" , "cowboy" , "go" , "revel" , "grails" , "lift" , "finagle"
, "scalatra" , "play-scala" , "play-slick" , "unfiltered"
],[ "kelp" , "plack" , "dancer" , "web-simple" , "mojolicious" , "flask"
, "django" , "tornado" , "rails" , "sinatra"
],[ "nancy" , "aspnet-mvc" , "servicestack" , "cpoll-pool" , "cpoll-cppsp"
, "dart" , "play1" , "vertx" , "gemini" , "spring" , "wicket" , "servlet"
, "tapestry" , "play-java" , "dropwizard" , "rest-express" , "play-java-jpa"
, "grizzly" , "openresty" , "php" , "yaf" , "cake" , "fuel" , "slim"
, "silex" , "kohana" , "laravel" , "lithium" , "phalcon" , "phreeze"
, "micromvc" , "symfony2" , "codeigniter"
],[ "onion" , "hapi" , "ringo" , "nodejs" , "express" , "ringo-conv"
]];
robustnessClusters=[[ "elli" , "cowboy" , "snap" , "yesod"
],[ "luminus" , "http-kit" , "compojure" , "play1" , "vertx" , "gemini"
, "spring" , "wicket" , "servlet" , "tapestry" , "play-java" , "dropwizard"
, "rest-express" , "play-java-jpa" , "grizzly" , "lift" , "finagle"
, "scalatra" , "play-scala" , "play-slick" , "unfiltered"
],[ "grails" , "hapi" , "ringo" , "nodejs" , "express" , "ringo-conv"
, "openresty" , "php" , "yaf" , "cake" , "fuel" , "slim" , "silex"
, "kohana" , "laravel" , "lithium" , "phalcon" , "phreeze" , "micromvc"
, "symfony2" , "codeigniter" , "flask" , "django" , "tornado" , "rails"
, "sinatra"
],[ "onion" , "nancy" , "aspnet-mvc" , "servicestack" , "cpoll-pool"
, "cpoll-cppsp" , "dart" , "go" , "revel" , "kelp" , "plack"
, "dancer" , "web-simple" , "mojolicious"
],[
],[
]];
// var essentialVector=[10000,100,1,0,0,0];
// var importantVector=[1024,256,64,16,4,1];
// var normalVector=[32,16,8,4,2,1];
// var somehowVector=[10,8,6,4,2,1];
// var whateverVector=[1,1,1,1,1,1];
var ninfty=Number.NEGATIVE_INFINITY;
var essentialVector=[11,7,0,-1000,-1000,-1000];
var importantVector=[10,8,6,4,2,0];
var normalVector=[5,4,3,2,1,0];
var somehowVector=[2,2,1,1,0,0];
var whateverVector=[0,0,0,0,0,0];
var framework=[];
for (var i=0;lt(i,efficiencyClusters.length);i++) {
for (var j=0;lt(j,efficiencyClusters[i].length);j++) {
framework[efficiencyClusters[i][j]]={};
}
}
$(["efficiency"
,"popularity"
,"expressiveness"
,"robustness"]).each(function(){
var tab;
eval("tab = "+this+"Clusters;");
for (var i=0;lt(i,tab.length);i++) {
for (var j=0;lt(j,tab[i].length);j++) {
eval("framework[tab[i][j]]."+this+"= i;");
}
}
});
function setLine(name,vector) {
$('#' + name+' td input').each(function(i){
var len = vector.length;
if (lt(i,len)) {
$(this).val(vector[i]); }});}
$(['t-expressiveness'
,'t-popularity'
,'t-efficiency'
,'t-robustness']).each(function(){
var name='#'+this;
var tdinput=$('<td align="right"><input style="display: inline-block;width:3.2em;text-align:right" type="text"></input></td>'.repeat(6));
$(name).append(tdinput);
$(name).append($('<td>'+
'<select style="width:6em" id="s-'+this+'">' +
'<option value="essential">Essential</option>' +
'<option value="important">Important</option>' +
'<option value="normal" selected="t">Normal</option>' +
'<option value="somehow">Somehow</option>' +
'<option value="whatever">Unsignificant</option>' +
'</select>' +
'</td>' ));
if (this == "t-expressiveness") {
setLine(this,essentialVector);
$(name+' select').val("essential");
} else if (this == "t-popularity") {
setLine(this,normalVector);
$(name+' select').val("normal");
} else if (this == "t-efficiency") {
setLine(this,importantVector);
$(name+' select').val("important");
} else if (this == "t-robustness") {
setLine(this,importantVector);
$(name+' select').val("important");
}
var strthis=''+this;
$("#s-"+this).change(function(){
var val=$("#s-"+strthis+" option:selected").val();
var tab;
eval('tab='+val+'Vector');
setLine(strthis,tab);
updateResult();
});
});
function updateResult(){
var scoreMatrix=[[0,0,0,0,0,0]
,[0,0,0,0,0,0]
,[0,0,0,0,0,0]
,[0,0,0,0,0,0]
];
$(['t-expressiveness'
,'t-popularity'
,'t-efficiency'
,'t-robustness']).each(function(i){
$("#"+this+" td input").each(function(j){
scoreMatrix[i][j]=$(this).val(); }) });
var result=[];
for (key in framework) {
framework[key].score =
parseInt(scoreMatrix[0][framework[key].expressiveness]) +
parseInt(scoreMatrix[1][framework[key].popularity]) +
parseInt(scoreMatrix[2][framework[key].efficiency]) +
parseInt(scoreMatrix[3][framework[key].robustness]);
result.push([key,framework[key].score]);
}
result.sort(function(a,b){return b[1] - a[1];});
var winners=[];
var i=0;
var maxscore=result[0][1];
while ((lt(i,result.length)) && (result[i][1]==maxscore)){
winners.push(result[i]);
i+=1;
}
if (winners.length == 1) {
$('#result').html('<'+'p style="text-align: center">And the winner is<'+'br/><'+'strong>'+result[0][0]+'<'+'/strong> ('+languageOf[result[0][0]]+')<'+'/p><'+'table><'+'tr><'+'th>position<'+'/th><'+'th>framework<'+'/th><'+'th>language<'+'/th><'+'th align="right">score<'+'/th><'+'/tr><'+'/table>');
} else {
var listwinners=new String;
for (i=0;lt(i,winners.length);i++){
listwinners=listwinners+bal('strong', winners[i][0] ) + " ("+languageOf[winners[i][0]]+")"+ret();}
$('#result').html('<'+'p style="text-align: center">And the winners are<'+'br/>' + listwinners + '<'+'table><'+'tr><'+'th>position<'+'/th><'+'th>framework<'+'/th><'+'th>language<'+'/th><'+'th align="right">score<'+'/th><'+'/tr><'+'/table>');
}
for (k=0;lt(k,10);k++){
$('#result table').append('<'+'tr><'+'td>'+(k+1)+'<'+'/td><'+'td>'+result[k][0]+'<'+'/td><'+'td>'+languageOf[result[k][0]]+'<'+'/td><'+'td><'+'code>'+result[k][1]+'<'+'/code><'+'/td><'+'/tr>');
}
}
$('#compute').click(updateResult);
$("#choice-matrix input[type='text']").change(updateResult);
$("#choice-matrix input[type='text']").keyup(updateResult);
updateResult();
// Show hide tables in the article
$('#toggle-expressiveness-table').click(function(){
$('#expressiveness-table').toggle();
});
$('#toggle-robustness-table').click(function(){
$('#robustness-table').toggle();
});
$('#expressiveness-table').toggle();
$('#robustness-table').toggle();
} else {
setTimeout(run,50);
}
}
run();
})();
// ]]&gt;</script>
<p>I didnt had the courage in explaining in what the scoring system is good. Mostly, if you use product instead of sum for the score you could use power of <span class="math inline"><em>e</em></span> for the values in the matrix. And you could see the matrix as a probability matrix (each line sum to 1). Which provide a slighly better intuition on whats going on.</p>
<p>Remember only that values are exponential. Do not double an already big value for example the effect would be extreme.</p>
<h2 id="conclusion">Conclusion</h2>
<p>All of this is based as most as I could on objective data. The choice method seems both rather rational and classical. It is now up to you to edit the score matrix to set your needs.</p>
<p>I know that in the current state there are many flaws. But it is a first system to help make a choice rationally.</p>
<p>I encourage you to go further if you are not satisfied by my method.</p>
<p>The source code for the matrix shouldnt be too hard to read. Just read the source of this webpage. You could change the positionning of some frameworks if you believe I made some mistake by placing them in some bad clusters.</p>
<p>So I hope this tool will help you in making your life easier.</p>]]></summary>
</entry>
<entry>
<title>Hakyll setup</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Hakyll-setup/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Hakyll-setup/index.html</id>
<published>2013-03-16T00:00:00Z</published>
<updated>2013-03-16T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Hakyll-setup/main.png" alt="Main image"/>
</div>
<div class="intro">
<p><span class="sc"><abbr title="Trop long; pas lu">tlpl</abbr>: </span> Comment jutilise <a href="http://jaspervdj.be/hakyll">hakyll</a>. Abréviations, corrections typographiques, multi-language, utilisation d<code>index.html</code>, etc…</p>
</div>
<p>Ce site web est fait avec <a href="http://jaspervdj.be/hakyll">Hakyll</a>.</p>
<p><a href="http://jaspervdj.be/hakyll">Hakyll</a> peut être vu comme un <span class="sc"><abbr title="Content Management System">cms</abbr></span> minimaliste. Dune façon plus générale, il sagit dune bibliothèque qui facilite la création automatique de fichiers.</p>
<p>Dun point de vue utilisateur voici comment jécris mes articles&nbsp;:</p>
<ol type="1">
<li>Jouvre un éditeur de texte (vim dans mon cas). Jédite un fichier markdow qui ressemble à ça :</li>
</ol>
<div class="sourceCode" id="cb1"><pre class="sourceCode markdown"><code class="sourceCode markdown"><a class="sourceLine" id="cb1-1" title="1">Un titre de page</a>
<a class="sourceLine" id="cb1-2" title="2">================</a>
<a class="sourceLine" id="cb1-3" title="3"></a>
<a class="sourceLine" id="cb1-4" title="4">Un titre de chapitre</a>
<a class="sourceLine" id="cb1-5" title="5">--------------------</a>
<a class="sourceLine" id="cb1-6" title="6"></a>
<a class="sourceLine" id="cb1-7" title="7">Azur, nos bêtes sont bondées d&#39;un cri.</a>
<a class="sourceLine" id="cb1-8" title="8">Je m&#39;éveille songeant au fruit noir de l&#39;anibe dans sa cupule</a>
<a class="sourceLine" id="cb1-9" title="9">véruqueuse et tronquée.</a>
<a class="sourceLine" id="cb1-10" title="10"></a>
<a class="sourceLine" id="cb1-11" title="11">Saint John Perse.</a>
<a class="sourceLine" id="cb1-12" title="12"></a>
<a class="sourceLine" id="cb1-13" title="13"><span class="fu">### Titre 3</span></a>
<a class="sourceLine" id="cb1-14" title="14"></a>
<a class="sourceLine" id="cb1-15" title="15">&gt;<span class="dt"> C&#39;est un blockquote.</span></a>
<a class="sourceLine" id="cb1-16" title="16"><span class="dt">&gt;</span></a>
<a class="sourceLine" id="cb1-17" title="17"><span class="dt">&gt; C&#39;est un second paragraphe dans le blockquote</span></a>
<a class="sourceLine" id="cb1-18" title="18"><span class="dt">&gt;</span></a>
<a class="sourceLine" id="cb1-19" title="19"><span class="dt">&gt; ## C&#39;est un H2 dans un blockquote</span></a></code></pre></div>
<ol start="2" type="1">
<li>Jouvre mon navigateur et je rafraichis de temps en temps pour voir les changements.</li>
<li>Une fois satisfait, je lance un script minimal qui fait grosso modo un simple <code>git push</code>. Mon blog est hébergé sur <a href="http://github.com">github</a>.</li>
</ol>
<p>A ne pas y regarder de trop près, on peut réduire le rôle dHakyll à&nbsp;:</p>
<blockquote>
<p>Créer (resp. mettre à jour) un fichier <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> lorsque je crée (resp. modifie) un fichier markdown.</p>
</blockquote>
<p>Bien que cela semble facile, il y a de nombreux détails cachés&nbsp;:</p>
<ul>
<li>Ajouter des métadatas comme des mots clés</li>
<li>Créer un page archive qui contient la liste de tous les articles</li>
<li>Gérer les fichier statiques</li>
<li>Créer un flux <span class="sc"><abbr title="Rich Site Summary">rss</abbr></span></li>
<li>Filtrer le contenu</li>
<li>Gérer les dépendances</li>
</ul>
<p>Le travail dHakyll est de vous aider avec tout ça. Commençons par expliquer les concepts basiques.</p>
<h2 id="les-concepts-et-la-syntaxe">Les concepts et la syntaxe</h2>
<div>
<img src="/Scratch/img/blog/Hakyll-setup/overview.png" alt="Overview"/>
</div>
<p>Pour chaque fichier que vous créer, il faut fournir&nbsp;:</p>
<ul>
<li>un chemin de destination</li>
<li>une liste de filtres du contenu</li>
</ul>
<p>Commençons par le cas le plus simple ; les fichiers statiques (images, fontes, etc…) Généralement, vous avec un répertoire source (ici le répertoire courant) et une répertoire destination <code>_site</code>.</p>
<p>Le code Hakyll est&nbsp;:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb2-1" title="1"><span class="co">-- pour chaque fichier dans le répertoire static</span></a>
<a class="sourceLine" id="cb2-2" title="2">match <span class="st">&quot;static/*&quot;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb2-3" title="3"> <span class="co">-- on ne change pas le nom ni le répertoire</span></a>
<a class="sourceLine" id="cb2-4" title="4"> route idRoute</a>
<a class="sourceLine" id="cb2-5" title="5"> <span class="co">-- on ne modifie pas le contenu</span></a>
<a class="sourceLine" id="cb2-6" title="6"> compile copyFileCompiler</a></code></pre></div>
<p>Ce programme va copier <code>static/foo.jpg</code> dans <code>_site/static/foo.jpg</code>. Cest un peu lourd pour un simple <code>cp</code>. Maintenant comment faire pour transformer automatiquement un fichier markdown dans le bon <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span>?</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb3-1" title="1"><span class="co">-- pour chaque fichier avec un extension md</span></a>
<a class="sourceLine" id="cb3-2" title="2">match <span class="st">&quot;posts/*.md&quot;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb3-3" title="3"> <span class="co">-- changer son extension en html</span></a>
<a class="sourceLine" id="cb3-4" title="4"> route <span class="op">$</span> setExtension <span class="st">&quot;html&quot;</span></a>
<a class="sourceLine" id="cb3-5" title="5"> <span class="co">-- utiliser la librairie pandoc pour compiler le markdown en html</span></a>
<a class="sourceLine" id="cb3-6" title="6"> compile <span class="op">$</span> pandocCompiler</a></code></pre></div>
<p>Si vous créez un fichier <code>posts/toto.md</code>, cela créera un fichier <code>_site/posts/toto.html</code>.</p>
<p>Si le fichier <code>posts/foo.md</code> contient</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode markdown"><code class="sourceCode markdown"><a class="sourceLine" id="cb4-1" title="1"><span class="fu"># Cthulhu</span></a>
<a class="sourceLine" id="cb4-2" title="2"></a>
<a class="sourceLine" id="cb4-3" title="3">ph&#39;nglui mglw&#39;nafh Cthulhu R&#39;lyeh wgah&#39;nagl fhtagn</a></code></pre></div>
<p>le fichier <code>_site/posts/foo.html</code>, contiendra</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb5-1" title="1"><span class="kw">&lt;h1&gt;</span>Cthulhu<span class="kw">&lt;/h1&gt;</span></a>
<a class="sourceLine" id="cb5-2" title="2"><span class="kw">&lt;p&gt;</span>ph&#39;nglui mglw&#39;nafh Cthulhu R&#39;lyeh wgah&#39;nagl fhtagn<span class="kw">&lt;/p&gt;</span></a></code></pre></div>
<p>Mais horreur ! <code>_site/posts/cthulhu.html</code> nest pas un <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> complet. Il ne possède ni header, ni footer, etc… Cest ici que nous utilisons des templates. Jajoute une nouvelle directive dans le bloc “compile”.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb6-1" title="1">match <span class="st">&quot;posts/*.md&quot;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb6-2" title="2"> route <span class="op">$</span> setExtension <span class="st">&quot;html&quot;</span></a>
<a class="sourceLine" id="cb6-3" title="3"> compile <span class="op">$</span> pandocCompiler</a>
<a class="sourceLine" id="cb6-4" title="4"> <span class="co">-- use the template with the current content</span></a>
<a class="sourceLine" id="cb6-5" title="5"> <span class="highlight"><span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/post.html&quot;</span> defaultContext</span></a></code></pre></div>
<p>Maintenant si <code>templates/posts.html</code> contient:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb7-1" title="1"><span class="kw">&lt;html&gt;</span></a>
<a class="sourceLine" id="cb7-2" title="2"> <span class="kw">&lt;head&gt;</span></a>
<a class="sourceLine" id="cb7-3" title="3"> <span class="kw">&lt;title&gt;</span>How could I get the title?<span class="kw">&lt;/title&gt;</span></a>
<a class="sourceLine" id="cb7-4" title="4"> <span class="kw">&lt;/head&gt;</span></a>
<a class="sourceLine" id="cb7-5" title="5"> <span class="kw">&lt;body&gt;</span></a>
<a class="sourceLine" id="cb7-6" title="6"> <span class="highlight">$body$</span></a>
<a class="sourceLine" id="cb7-7" title="7"> <span class="kw">&lt;/body&gt;</span></a>
<a class="sourceLine" id="cb7-8" title="8"><span class="kw">&lt;/html&gt;</span></a></code></pre></div>
<p>Maintenant notre <code>ctuhlhu.html</code> contient</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb8-1" title="1"><span class="kw">&lt;html&gt;</span></a>
<a class="sourceLine" id="cb8-2" title="2"> <span class="kw">&lt;head&gt;</span></a>
<a class="sourceLine" id="cb8-3" title="3"> <span class="kw">&lt;title&gt;</span>How could I get the title?<span class="kw">&lt;/title&gt;</span></a>
<a class="sourceLine" id="cb8-4" title="4"> <span class="kw">&lt;/head&gt;</span></a>
<a class="sourceLine" id="cb8-5" title="5"> <span class="kw">&lt;body&gt;</span></a>
<a class="sourceLine" id="cb8-6" title="6"> <span class="highlight"><span class="kw">&lt;h1&gt;</span>Cthulhu<span class="kw">&lt;/h1&gt;</span></span></a>
<a class="sourceLine" id="cb8-7" title="7"> <span class="highlight"><span class="kw">&lt;p&gt;</span>ph&#39;nglui mglw&#39;nafh Cthulhu R&#39;lyeh wgah&#39;nagl fhtagn<span class="kw">&lt;/p&gt;</span></span></a>
<a class="sourceLine" id="cb8-8" title="8"> <span class="kw">&lt;/body&gt;</span></a>
<a class="sourceLine" id="cb8-9" title="9"><span class="kw">&lt;/html&gt;</span></a></code></pre></div>
<p>Cest facile. Mais il reste un problème à résoudre. Comment pouvons-nous changer le titre ? Ou par exemple, ajouter des mots clés ?</p>
<p>La solution est dutiliser les <code>Context</code>s. Pour cela, nous devrons ajouter des <em>metadonnées</em> à notre markdown<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a>.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode markdown"><code class="sourceCode markdown"><a class="sourceLine" id="cb9-1" title="1"><span class="highlight">--- </span></a>
<a class="sourceLine" id="cb9-2" title="2"><span class="highlight">title: Cthulhu</span></a>
<a class="sourceLine" id="cb9-3" title="3"><span class="highlight">--- </span></a>
<a class="sourceLine" id="cb9-4" title="4"><span class="fu"># Cthulhu</span></a>
<a class="sourceLine" id="cb9-5" title="5"></a>
<a class="sourceLine" id="cb9-6" title="6">ph&#39;nglui mglw&#39;nafh Cthulhu R&#39;lyeh wgah&#39;nagl fhtagn</a></code></pre></div>
<p>Et modifier légèrement notre template&nbsp;:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb10-1" title="1"><span class="kw">&lt;html&gt;</span></a>
<a class="sourceLine" id="cb10-2" title="2"> <span class="kw">&lt;head&gt;</span></a>
<a class="sourceLine" id="cb10-3" title="3"> <span class="kw">&lt;title&gt;</span><span class="highlight">$title$</span><span class="kw">&lt;/title&gt;</span></a>
<a class="sourceLine" id="cb10-4" title="4"> <span class="kw">&lt;/head&gt;</span></a>
<a class="sourceLine" id="cb10-5" title="5"> <span class="kw">&lt;body&gt;</span></a>
<a class="sourceLine" id="cb10-6" title="6"> $body$</a>
<a class="sourceLine" id="cb10-7" title="7"> <span class="kw">&lt;/body&gt;</span></a>
<a class="sourceLine" id="cb10-8" title="8"><span class="kw">&lt;/html&gt;</span></a></code></pre></div>
<p>Super facile!</p>
<p>La suite de larticle est en Anglais. Je la traduirai volontier si suffisamment de personnes me le demande gentillement.</p>
<h2 id="real-customization">Real customization</h2>
<p>Now that we understand the basic functionality. How to:</p>
<ul>
<li>use SASS?</li>
<li>add keywords?</li>
<li>simplify <span class="sc"><abbr title="Uniform Ressource Locator">url</abbr></span>?</li>
<li>create an archive page?</li>
<li>create an <span class="sc"><abbr title="Rich Site Summary">rss</abbr></span> feed?</li>
<li>filter the content?</li>
<li>add abbreviations support?</li>
<li>manage two languages?</li>
</ul>
<h3 id="use-sass">Use SASS</h3>
<p>Thats easy. Simply call the executable using <code>unixFilter</code>. Of course youll have to install SASS (<code>gem install sass</code>). And we also use compressCss to gain some space.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb11-1" title="1">match <span class="st">&quot;css/*&quot;</span> <span class="op">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb11-2" title="2"> route <span class="op">$</span> setExtension <span class="st">&quot;css&quot;</span></a>
<a class="sourceLine" id="cb11-3" title="3"> compile <span class="op">$</span> getResourceString <span class="op">&gt;&gt;=</span></a>
<a class="sourceLine" id="cb11-4" title="4"> withItemBody (unixFilter <span class="st">&quot;sass&quot;</span> [<span class="st">&quot;--trace&quot;</span>]) <span class="op">&gt;&gt;=</span></a>
<a class="sourceLine" id="cb11-5" title="5"> <span class="fu">return</span> <span class="op">.</span> <span class="fu">fmap</span> compressCss</a></code></pre></div>
<h3 id="add-keywords">Add keywords</h3>
<p>In order to help to reference your website on the web, it is nice to add some keywords as meta datas to your <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> page.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb12-1" title="1"><span class="kw">&lt;meta</span><span class="ot"> name=</span><span class="st">&quot;keywords&quot;</span></a>
<a class="sourceLine" id="cb12-2" title="2"><span class="ot"> content=</span><span class="st">&quot;Cthulhu, Yog-Sothoth, Shub-Niggurath&quot;</span><span class="kw">&gt;</span></a></code></pre></div>
<p>In order to add keywords, we could not directly use the markdown metadatas. Because, without any, there should be any meta tag in the <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span>.</p>
<p>An easy answer is to create a <code>Context</code> that will contains the meta tag.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb13-1" title="1"><span class="co">-- metaKeywordContext will return a Context containing a String</span></a>
<a class="sourceLine" id="cb13-2" title="2"><span class="ot">metaKeywordContext ::</span> <span class="dt">Context</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb13-3" title="3"><span class="co">-- can be reached using $metaKeywords$ in the templates</span></a>
<a class="sourceLine" id="cb13-4" title="4"><span class="co">-- Use the current item (markdown file)</span></a>
<a class="sourceLine" id="cb13-5" title="5">metaKeywordContext <span class="ot">=</span> field <span class="st">&quot;metaKeywords&quot;</span> <span class="op">$</span> \item <span class="ot">-&gt;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb13-6" title="6"> <span class="co">-- tags contains the content of the &quot;tags&quot; metadata</span></a>
<a class="sourceLine" id="cb13-7" title="7"> <span class="co">-- inside the item (understand the source)</span></a>
<a class="sourceLine" id="cb13-8" title="8"> tags <span class="ot">&lt;-</span> getMetadataField (itemIdentifier item) <span class="st">&quot;tags&quot;</span></a>
<a class="sourceLine" id="cb13-9" title="9"> <span class="co">-- if tags is empty return an empty string</span></a>
<a class="sourceLine" id="cb13-10" title="10"> <span class="co">-- in the other case return</span></a>
<a class="sourceLine" id="cb13-11" title="11"> <span class="co">-- &lt;meta name=&quot;keywords&quot; content=&quot;$tags$&quot;&gt;</span></a>
<a class="sourceLine" id="cb13-12" title="12"> <span class="fu">return</span> <span class="op">$</span> <span class="fu">maybe</span> <span class="st">&quot;&quot;</span> showMetaTags tags</a>
<a class="sourceLine" id="cb13-13" title="13"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb13-14" title="14"> showMetaTags t <span class="ot">=</span> <span class="st">&quot;&lt;meta name=\&quot;keywords\&quot; content=\&quot;&quot;</span></a>
<a class="sourceLine" id="cb13-15" title="15"> <span class="op">++</span> t <span class="op">++</span> <span class="st">&quot;\&quot;&gt;\n&quot;</span></a></code></pre></div>
<p>Then we pass this <code>Context</code> to the <code>loadAndApplyTemplate</code> function:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb14-1" title="1">match <span class="st">&quot;posts/*.md&quot;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb14-2" title="2"> route <span class="op">$</span> setExtension <span class="st">&quot;html&quot;</span></a>
<a class="sourceLine" id="cb14-3" title="3"> compile <span class="op">$</span> pandocCompiler</a>
<a class="sourceLine" id="cb14-4" title="4"> <span class="co">-- use the template with the current content</span></a>
<a class="sourceLine" id="cb14-5" title="5"> <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/post.html&quot;</span></a>
<a class="sourceLine" id="cb14-6" title="6"> (defaultContext <span class="highlight"><span class="op">&lt;&gt;</span> metaKeywordContext</span>)</a></code></pre></div>
<blockquote>
<p>☞ Here are the imports I use for this tutorial.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb15-1" title="1"><span class="ot">{-# LANGUAGE OverloadedStrings #-}</span></a>
<a class="sourceLine" id="cb15-2" title="2"><span class="kw">import</span> <span class="dt">Control.Monad</span> (forM,forM_)</a>
<a class="sourceLine" id="cb15-3" title="3"><span class="kw">import</span> <span class="dt">Data.List</span> (sortBy,isInfixOf)</a>
<a class="sourceLine" id="cb15-4" title="4"><span class="kw">import</span> <span class="dt">Data.Monoid</span> ((&lt;&gt;),mconcat)</a>
<a class="sourceLine" id="cb15-5" title="5"><span class="kw">import</span> <span class="dt">Data.Ord</span> (comparing)</a>
<a class="sourceLine" id="cb15-6" title="6"><span class="kw">import</span> <span class="dt">Hakyll</span></a>
<a class="sourceLine" id="cb15-7" title="7"><span class="kw">import</span> <span class="dt">System.Locale</span> (defaultTimeLocale)</a>
<a class="sourceLine" id="cb15-8" title="8"><span class="kw">import</span> <span class="dt">System.FilePath.Posix</span> (takeBaseName,takeDirectory</a>
<a class="sourceLine" id="cb15-9" title="9"> ,(<span class="op">&lt;/&gt;</span>),splitFileName)</a></code></pre></div>
</blockquote>
<h3 id="simplify-url">Simplify <span class="sc"><abbr title="Uniform Ressource Locator">url</abbr></span></h3>
<p>What I mean is to use url of the form:</p>
<pre><code>http://domain.name/post/title-of-the-post/</code></pre>
<p>I prefer this than having to add file with <code>.html</code> extension. We have to change the default Hakyll route behavior. We create another function <code>niceRoute</code>.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb17-1" title="1"><span class="co">-- replace a foo/bar.md by foo/bar/index.html</span></a>
<a class="sourceLine" id="cb17-2" title="2"><span class="co">-- this way the url looks like: foo/bar in most browsers</span></a>
<a class="sourceLine" id="cb17-3" title="3"><span class="ot">niceRoute ::</span> <span class="dt">Routes</span></a>
<a class="sourceLine" id="cb17-4" title="4">niceRoute <span class="ot">=</span> customRoute createIndexRoute</a>
<a class="sourceLine" id="cb17-5" title="5"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb17-6" title="6"> createIndexRoute ident <span class="ot">=</span></a>
<a class="sourceLine" id="cb17-7" title="7"> takeDirectory p <span class="op">&lt;/&gt;</span> takeBaseName p <span class="op">&lt;/&gt;</span> <span class="st">&quot;index.html&quot;</span></a>
<a class="sourceLine" id="cb17-8" title="8"> <span class="kw">where</span> p<span class="ot">=</span>toFilePath ident</a></code></pre></div>
<p>Not too difficult. But! There might be a problem. What if there is a <code>foo/index.html</code> link instead of a clean <code>foo/</code> in some content?</p>
<p>Very simple, we simply remove all <code>/index.html</code> to all our links.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb18-1" title="1"><span class="co">-- replace url of the form foo/bar/index.html by foo/bar</span></a>
<a class="sourceLine" id="cb18-2" title="2"><span class="ot">removeIndexHtml ::</span> <span class="dt">Item</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Compiler</span> (<span class="dt">Item</span> <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb18-3" title="3">removeIndexHtml item <span class="ot">=</span> <span class="fu">return</span> <span class="op">$</span> <span class="fu">fmap</span> (withUrls removeIndexStr) item</a>
<a class="sourceLine" id="cb18-4" title="4"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb18-5" title="5"><span class="ot"> removeIndexStr ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb18-6" title="6"> removeIndexStr url <span class="ot">=</span> <span class="kw">case</span> splitFileName url <span class="kw">of</span></a>
<a class="sourceLine" id="cb18-7" title="7"> (dir, <span class="st">&quot;index.html&quot;</span>) <span class="op">|</span> isLocal dir <span class="ot">-&gt;</span> dir</a>
<a class="sourceLine" id="cb18-8" title="8"> _ <span class="ot">-&gt;</span> url</a>
<a class="sourceLine" id="cb18-9" title="9"> <span class="kw">where</span> isLocal uri <span class="ot">=</span> <span class="fu">not</span> (isInfixOf <span class="st">&quot;://&quot;</span> uri)</a></code></pre></div>
<p>And we apply this filter at the end of our compilation</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb19-1" title="1">match <span class="st">&quot;posts/*.md&quot;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb19-2" title="2"> <span class="highlight">route <span class="op">$</span> niceRoute</span></a>
<a class="sourceLine" id="cb19-3" title="3"> compile <span class="op">$</span> pandocCompiler</a>
<a class="sourceLine" id="cb19-4" title="4"> <span class="co">-- use the template with the current content</span></a>
<a class="sourceLine" id="cb19-5" title="5"> <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/post.html&quot;</span> defaultContext</a>
<a class="sourceLine" id="cb19-6" title="6"> <span class="highlight"><span class="op">&gt;&gt;=</span> removeIndexHtml</span></a></code></pre></div>
<h3 id="create-an-archive-page">Create an archive page</h3>
<p>Creating an archive start to be difficult. There is an example in the default Hakyll example. Unfortunately, it assumes all posts prefix their name with a date like in <code>2013-03-20-My-New-Post.md</code>.</p>
<p>I migrated from an older blog and didnt want to change my <span class="sc"><abbr title="Uniform Ressource Locator">url</abbr></span>. Also I prefer not to use any filename convention. Therefore, I add the date information in the metadata <code>published</code>. And the solution is here:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb20-1" title="1">match <span class="st">&quot;archive.md&quot;</span> <span class="op">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb20-2" title="2"> route <span class="op">$</span> niceRoute</a>
<a class="sourceLine" id="cb20-3" title="3"> compile <span class="op">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb20-4" title="4"> body <span class="ot">&lt;-</span> getResourceBody</a>
<a class="sourceLine" id="cb20-5" title="5"> <span class="fu">return</span> <span class="op">$</span> renderPandoc body</a>
<a class="sourceLine" id="cb20-6" title="6"> <span class="highlight"><span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/archive.html&quot;</span> archiveCtx</span></a>
<a class="sourceLine" id="cb20-7" title="7"> <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="highlight"><span class="st">&quot;templates/base.html&quot;</span></span> defaultContext</a>
<a class="sourceLine" id="cb20-8" title="8"> <span class="op">&gt;&gt;=</span> removeIndexHtml</a></code></pre></div>
<p>Where <code>templates/archive.html</code> contains</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb21-1" title="1">$body$</a>
<a class="sourceLine" id="cb21-2" title="2"></a>
<a class="sourceLine" id="cb21-3" title="3"><span class="kw">&lt;ul&gt;</span></a>
<a class="sourceLine" id="cb21-4" title="4"> $posts$</a>
<a class="sourceLine" id="cb21-5" title="5"><span class="kw">&lt;/ul&gt;</span></a></code></pre></div>
<p>And <code>base.html</code> is a standard template (simpler than <code>post.html</code>).</p>
<p><code>archiveCtx</code> provide a context containing an <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> representation of a list of posts in the metadata named <code>posts</code>. It will be used in the <code>templates/archive.html</code> file with <code>$posts$</code>.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb22-1" title="1">archiveCtx <span class="ot">=</span></a>
<a class="sourceLine" id="cb22-2" title="2"> defaultContext <span class="op">&lt;&gt;</span></a>
<a class="sourceLine" id="cb22-3" title="3"> metaKeywordContext <span class="op">&lt;&gt;</span></a>
<a class="sourceLine" id="cb22-4" title="4"> <span class="highlight">field <span class="st">&quot;posts&quot;</span> (\_ <span class="ot">-&gt;</span> postList createdFirst)</span></a></code></pre></div>
<p><code>postList</code> returns an <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> representation of a list of posts given an Item sort function. The representation will apply a minimal template on all posts. Then it concatenate all the results. The template is <code>post-item.html</code>:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb23-1" title="1"><span class="kw">&lt;li&gt;&lt;a</span><span class="ot"> href=</span><span class="st">&quot;$url$&quot;</span><span class="kw">&gt;</span>$published$ - $title$<span class="kw">&lt;/a&gt;&lt;/li&gt;</span></a></code></pre></div>
<p>Here is how it is done:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb24-1" title="1"><span class="ot">postList ::</span> [<span class="dt">Item</span> <span class="dt">String</span>] <span class="ot">-&gt;</span> <span class="dt">Compiler</span> [<span class="dt">Item</span> <span class="dt">String</span>]</a>
<a class="sourceLine" id="cb24-2" title="2"> <span class="ot">-&gt;</span> <span class="dt">Compiler</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb24-3" title="3">postList sortFilter <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb24-4" title="4"> <span class="co">-- sorted posts</span></a>
<a class="sourceLine" id="cb24-5" title="5"> posts <span class="ot">&lt;-</span> loadAll <span class="st">&quot;post/*&quot;</span> <span class="op">&gt;&gt;=</span> sortFilter</a>
<a class="sourceLine" id="cb24-6" title="6"> itemTpl <span class="ot">&lt;-</span> loadBody <span class="st">&quot;templates/post-item.html&quot;</span></a>
<a class="sourceLine" id="cb24-7" title="7"> <span class="co">-- we apply the template to all post</span></a>
<a class="sourceLine" id="cb24-8" title="8"> <span class="co">-- and we concatenate the result.</span></a>
<a class="sourceLine" id="cb24-9" title="9"> <span class="co">-- list is a string</span></a>
<a class="sourceLine" id="cb24-10" title="10"> list <span class="ot">&lt;-</span> applyTemplateList itemTpl defaultContext posts</a>
<a class="sourceLine" id="cb24-11" title="11"> <span class="fu">return</span> list</a></code></pre></div>
<p><code>createdFirst</code> sort a list of item and put it inside <code>Compiler</code> context. We need to be in the <code>Compiler</code> context to access metadatas.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb25-1" title="1"><span class="ot">createdFirst ::</span> [<span class="dt">Item</span> <span class="dt">String</span>] <span class="ot">-&gt;</span> <span class="dt">Compiler</span> [<span class="dt">Item</span> <span class="dt">String</span>]</a>
<a class="sourceLine" id="cb25-2" title="2">createdFirst items <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb25-3" title="3"> <span class="co">-- itemsWithTime is a list of couple (date,item)</span></a>
<a class="sourceLine" id="cb25-4" title="4"> itemsWithTime <span class="ot">&lt;-</span> forM items <span class="op">$</span> \item <span class="ot">-&gt;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb25-5" title="5"> <span class="co">-- getItemUTC will look for the metadata &quot;published&quot; or &quot;date&quot;</span></a>
<a class="sourceLine" id="cb25-6" title="6"> <span class="co">-- then it will try to get the date from some standard formats</span></a>
<a class="sourceLine" id="cb25-7" title="7"> utc <span class="ot">&lt;-</span> getItemUTC defaultTimeLocale <span class="op">$</span> itemIdentifier item</a>
<a class="sourceLine" id="cb25-8" title="8"> <span class="fu">return</span> (utc,item)</a>
<a class="sourceLine" id="cb25-9" title="9"> <span class="co">-- we return a sorted item list</span></a>
<a class="sourceLine" id="cb25-10" title="10"> <span class="fu">return</span> <span class="op">$</span> <span class="fu">map</span> <span class="fu">snd</span> <span class="op">$</span> <span class="fu">reverse</span> <span class="op">$</span> sortBy (comparing <span class="fu">fst</span>) itemsWithTime</a></code></pre></div>
<p>It wasnt so easy. But it works pretty well.</p>
<h3 id="create-an-rss-feed">Create an <span class="sc"><abbr title="Rich Site Summary">rss</abbr></span> feed</h3>
<p>To create an <span class="sc"><abbr title="Rich Site Summary">rss</abbr></span> feed, we have to:</p>
<ul>
<li>select only the lasts posts.</li>
<li>generate partially rendered posts (no css, js, etc…)</li>
</ul>
<p>We could then render the posts twice. One for <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> rendering and another time for <span class="sc"><abbr title="Rich Site Summary">rss</abbr></span>. Remark we need to generate the <span class="sc"><abbr title="Rich Site Summary">rss</abbr></span> version to create the <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> one.</p>
<p>One of the great feature of Hakyll is to be able to save snapshots. Here is how:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb26-1" title="1">match <span class="st">&quot;posts/*.md&quot;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb26-2" title="2"> route <span class="op">$</span> setExtension <span class="st">&quot;html&quot;</span></a>
<a class="sourceLine" id="cb26-3" title="3"> compile <span class="op">$</span> pandocCompiler</a>
<a class="sourceLine" id="cb26-4" title="4"> <span class="co">-- save a snapshot to be used later in rss generation</span></a>
<a class="sourceLine" id="cb26-5" title="5"> <span class="highlight"><span class="op">&gt;&gt;=</span> saveSnapshot <span class="st">&quot;content&quot;</span></span></a>
<a class="sourceLine" id="cb26-6" title="6"> <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/post.html&quot;</span> defaultContext</a></code></pre></div>
<p>Now for each post there is a snapshot named “content” associated. The snapshots are created before applying a template and after applying pandoc. Furthermore feed dont need a source markdown file. Then we create a new file from no one. Instead of using <code>match</code>, we use <code>create</code>:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb27-1" title="1">create [<span class="st">&quot;feed.xml&quot;</span>] <span class="op">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb27-2" title="2"> route idRoute</a>
<a class="sourceLine" id="cb27-3" title="3"> compile <span class="op">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb27-4" title="4"> <span class="co">-- load all &quot;content&quot; snapshots of all posts</span></a>
<a class="sourceLine" id="cb27-5" title="5"> loadAllSnapshots <span class="st">&quot;posts/*&quot;</span> <span class="st">&quot;content&quot;</span></a>
<a class="sourceLine" id="cb27-6" title="6"> <span class="co">-- take the latest 10</span></a>
<a class="sourceLine" id="cb27-7" title="7"> <span class="op">&gt;&gt;=</span> (<span class="fu">fmap</span> (<span class="fu">take</span> <span class="dv">10</span>)) <span class="op">.</span> createdFirst</a>
<a class="sourceLine" id="cb27-8" title="8"> <span class="co">-- renderAntom feed using some configuration</span></a>
<a class="sourceLine" id="cb27-9" title="9"> <span class="op">&gt;&gt;=</span> renderAtom feedConfiguration feedCtx</a>
<a class="sourceLine" id="cb27-10" title="10"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb27-11" title="11"><span class="ot"> feedCtx ::</span> <span class="dt">Context</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb27-12" title="12"> feedCtx <span class="ot">=</span> defaultContext <span class="op">&lt;&gt;</span></a>
<a class="sourceLine" id="cb27-13" title="13"> <span class="co">-- $description$ will render as the post body</span></a>
<a class="sourceLine" id="cb27-14" title="14"> <span class="highlight">bodyField <span class="st">&quot;description&quot;</span></span></a></code></pre></div>
<p>The <code>feedConfiguration</code> contains some general informations about the feed.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb28-1" title="1"><span class="ot">feedConfiguration ::</span> <span class="dt">FeedConfiguration</span></a>
<a class="sourceLine" id="cb28-2" title="2">feedConfiguration <span class="ot">=</span> <span class="dt">FeedConfiguration</span></a>
<a class="sourceLine" id="cb28-3" title="3"> { feedTitle <span class="ot">=</span> <span class="st">&quot;Great Old Ones&quot;</span></a>
<a class="sourceLine" id="cb28-4" title="4"> , feedDescription <span class="ot">=</span> <span class="st">&quot;This feed provide information about Great Old Ones&quot;</span></a>
<a class="sourceLine" id="cb28-5" title="5"> , feedAuthorName <span class="ot">=</span> <span class="st">&quot;Abdul Alhazred&quot;</span></a>
<a class="sourceLine" id="cb28-6" title="6"> , feedAuthorEmail <span class="ot">=</span> <span class="st">&quot;abdul.alhazred@great-old-ones.com&quot;</span></a>
<a class="sourceLine" id="cb28-7" title="7"> , feedRoot <span class="ot">=</span> <span class="st">&quot;http://great-old-ones.com&quot;</span></a>
<a class="sourceLine" id="cb28-8" title="8"> }</a></code></pre></div>
<p>Great idea certainly steal from <a href="http://nanoc.ws">nanoc</a> (my previous blog engine)!</p>
<h3 id="filter-the-content">Filter the content</h3>
<p>As I just said, <a href="http://nanoc.ws">nanoc</a> was my preceding blog engine. It is written in Ruby and as Hakyll, it is quite awesome. And one thing Ruby does more naturally than Haskell is regular expressions. I had a <em>lot</em> of filters in nanoc. I lost some because I dont use them much. But I wanted to keep some. Generally, filtering the content is just a way to apply to the body a function of type <code>String -&gt; String</code>.</p>
<p>Also we generally want prefilters (to filter the markdown) and postfilters (to filter the <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span> after the pandoc compilation).</p>
<p>Here is how I do it:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb29-1" title="1">markdownPostBehavior <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb29-2" title="2"> route <span class="op">$</span> niceRoute</a>
<a class="sourceLine" id="cb29-3" title="3"> compile <span class="op">$</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb29-4" title="4"> body <span class="ot">&lt;-</span> getResourceBody</a>
<a class="sourceLine" id="cb29-5" title="5"> <span class="highlight">prefilteredText <span class="ot">&lt;-</span> <span class="fu">return</span> <span class="op">$</span> (<span class="fu">fmap</span> preFilters body)</span></a>
<a class="sourceLine" id="cb29-6" title="6"> <span class="highlight"><span class="fu">return</span> <span class="op">$</span> renderPandoc prefilteredText</span></a>
<a class="sourceLine" id="cb29-7" title="7"> <span class="highlight"><span class="op">&gt;&gt;=</span> applyFilter postFilters</span></a>
<a class="sourceLine" id="cb29-8" title="8"> <span class="op">&gt;&gt;=</span> saveSnapshot <span class="st">&quot;content&quot;</span></a>
<a class="sourceLine" id="cb29-9" title="9"> <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/post.html&quot;</span> yContext</a>
<a class="sourceLine" id="cb29-10" title="10"> <span class="op">&gt;&gt;=</span> loadAndApplyTemplate <span class="st">&quot;templates/boilerplate.html&quot;</span> yContext</a>
<a class="sourceLine" id="cb29-11" title="11"> <span class="op">&gt;&gt;=</span> relativizeUrls</a>
<a class="sourceLine" id="cb29-12" title="12"> <span class="op">&gt;&gt;=</span> removeIndexHtml</a></code></pre></div>
<p>Where</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb30-1" title="1">applyFilter strfilter str <span class="ot">=</span> <span class="fu">return</span> <span class="op">$</span> (<span class="fu">fmap</span> <span class="op">$</span> strfilter) str</a>
<a class="sourceLine" id="cb30-2" title="2"><span class="ot">preFilters ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb30-3" title="3"><span class="ot">postFilters ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a></code></pre></div>
<p>Now we have a simple way to filter the content. Lets augment the markdown ability.</p>
<h3 id="add-abbreviations-support">Add abbreviations support</h3>
<p>Comparing to <span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span>, a very annoying markdown limitation is the lack of abbreviations.</p>
<p>Fortunately we can filter our content. And here is the filter I use:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb31-1" title="1"><span class="ot">abbreviationFilter ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb31-2" title="2">abbreviationFilter <span class="ot">=</span> replaceAll <span class="st">&quot;%[a-zA-Z0-9_]*&quot;</span> newnaming</a>
<a class="sourceLine" id="cb31-3" title="3"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb31-4" title="4"> newnaming matched <span class="ot">=</span> <span class="kw">case</span> M.lookup (<span class="fu">tail</span> matched) abbreviations <span class="kw">of</span></a>
<a class="sourceLine" id="cb31-5" title="5"> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> matched</a>
<a class="sourceLine" id="cb31-6" title="6"> <span class="dt">Just</span> v <span class="ot">-&gt;</span> v</a>
<a class="sourceLine" id="cb31-7" title="7"><span class="ot">abbreviations ::</span> <span class="dt">Map</span> <span class="dt">String</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb31-8" title="8">abbreviations <span class="ot">=</span> M.fromList</a>
<a class="sourceLine" id="cb31-9" title="9"> [ (<span class="st">&quot;html&quot;</span>, <span class="st">&quot;&lt;span class=\&quot;sc\&quot;&gt;html&lt;/span&gt;&quot;</span>)</a>
<a class="sourceLine" id="cb31-10" title="10"> , (<span class="st">&quot;css&quot;</span>, <span class="st">&quot;&lt;span class=\&quot;sc\&quot;&gt;css&lt;/span&gt;&quot;</span>)</a>
<a class="sourceLine" id="cb31-11" title="11"> , (<span class="st">&quot;svg&quot;</span>, <span class="st">&quot;&lt;span class=\&quot;sc\&quot;&gt;svg&lt;/span&gt;&quot;</span>)</a>
<a class="sourceLine" id="cb31-12" title="12"> , (<span class="st">&quot;xml&quot;</span>, <span class="st">&quot;&lt;span class=\&quot;sc\&quot;&gt;xml&lt;/span&gt;&quot;</span>)</a>
<a class="sourceLine" id="cb31-13" title="13"> , (<span class="st">&quot;xslt&quot;</span>, <span class="st">&quot;&lt;span class=\&quot;sc\&quot;&gt;xslt&lt;/span&gt;&quot;</span>) ]</a></code></pre></div>
<p>It will search for all string starting by % and it will search in the <code>Map</code> if there is a corresponding abbreviation. If there is one, we replace the content. Otherwise we do nothing.</p>
<p>Do you really believe I type</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode html wrap"><code class="sourceCode html"><a class="sourceLine" id="cb32-1" title="1"><span class="kw">&lt;span</span><span class="ot"> style=</span><span class="st">&quot;text-transform: uppercase&quot;</span><span class="kw">&gt;</span>L<span class="kw">&lt;sup</span><span class="ot"> style=</span><span class="st">&quot;vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em&quot;</span><span class="kw">&gt;</span>a<span class="kw">&lt;/sup&gt;</span>T<span class="kw">&lt;sub</span><span class="ot"> style=</span><span class="st">&quot;vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em&quot;</span><span class="kw">&gt;</span>e<span class="kw">&lt;/sub&gt;</span>X<span class="kw">&lt;/span&gt;</span></a></code></pre></div>
<p>each time I write <span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span>?</p>
<h3 id="manage-two-languages">Manage two languages</h3>
<p>Generally I write my post in English and French. And this is more difficult than it appears. For example, I need to filter the language in order to get the right list of posts. I also use some words in the templates and I want them to be translated.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb33-1" title="1"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;$otherLanguagePath$&quot;</span></a>
<a class="sourceLine" id="cb33-2" title="2"><span class="ot"> onclick=</span><span class="st">&quot;setLanguage(&#39;$otherlanguage$&#39;)&quot;</span><span class="kw">&gt;</span></a>
<a class="sourceLine" id="cb33-3" title="3"> <span class="highlight">$changeLanguage$</span> <span class="kw">&lt;/a&gt;</span></a></code></pre></div>
<p>First I create a Map containing all translations.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb34-1" title="1"><span class="kw">data</span> <span class="dt">Trad</span> <span class="ot">=</span> <span class="dt">Trad</span> {<span class="ot"> frTrad ::</span> <span class="dt">String</span>,<span class="ot"> enTrad ::</span> <span class="dt">String</span> }</a>
<a class="sourceLine" id="cb34-2" title="2"></a>
<a class="sourceLine" id="cb34-3" title="3"><span class="ot">trads ::</span> <span class="dt">Map</span> <span class="dt">String</span> <span class="dt">Trad</span></a>
<a class="sourceLine" id="cb34-4" title="4">trads <span class="ot">=</span> M.fromList <span class="op">$</span> <span class="fu">map</span> toTrad [</a>
<a class="sourceLine" id="cb34-5" title="5"> (<span class="st">&quot;changeLanguage&quot;</span>,</a>
<a class="sourceLine" id="cb34-6" title="6"> (<span class="st">&quot;English&quot;</span></a>
<a class="sourceLine" id="cb34-7" title="7"> , <span class="st">&quot;Français&quot;</span>))</a>
<a class="sourceLine" id="cb34-8" title="8"> ,(<span class="st">&quot;switchCss&quot;</span>,</a>
<a class="sourceLine" id="cb34-9" title="9"> (<span class="st">&quot;Changer de theme&quot;</span></a>
<a class="sourceLine" id="cb34-10" title="10"> ,<span class="st">&quot;Change Theme&quot;</span>))</a>
<a class="sourceLine" id="cb34-11" title="11"> ,(<span class="st">&quot;socialPrivacy&quot;</span>,</a>
<a class="sourceLine" id="cb34-12" title="12"> (<span class="st">&quot;Ces liens sociaux préservent votre vie privée&quot;</span></a>
<a class="sourceLine" id="cb34-13" title="13"> ,<span class="st">&quot;These social sharing links preserve your privacy&quot;</span>))</a>
<a class="sourceLine" id="cb34-14" title="14"> ]</a>
<a class="sourceLine" id="cb34-15" title="15"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb34-16" title="16"> toTrad (key,(french,english)) <span class="ot">=</span></a>
<a class="sourceLine" id="cb34-17" title="17"> (key, <span class="dt">Trad</span> { frTrad <span class="ot">=</span> french , enTrad <span class="ot">=</span> english })</a></code></pre></div>
<p>Then I create a context for all key:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb35-1" title="1"><span class="ot">tradsContext ::</span> <span class="dt">Context</span> a</a>
<a class="sourceLine" id="cb35-2" title="2">tradsContext <span class="ot">=</span> <span class="fu">mconcat</span> (<span class="fu">map</span> addTrad (M.keys trads))</a>
<a class="sourceLine" id="cb35-3" title="3"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb35-4" title="4"><span class="ot"> addTrad ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Context</span> a</a>
<a class="sourceLine" id="cb35-5" title="5"> addTrad name <span class="ot">=</span></a>
<a class="sourceLine" id="cb35-6" title="6"> field name <span class="op">$</span> \item <span class="ot">-&gt;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb35-7" title="7"> lang <span class="ot">&lt;-</span> itemLang item</a>
<a class="sourceLine" id="cb35-8" title="8"> <span class="kw">case</span> M.lookup name trads <span class="kw">of</span></a>
<a class="sourceLine" id="cb35-9" title="9"> <span class="dt">Just</span> (<span class="dt">Trad</span> lmap) <span class="ot">-&gt;</span> <span class="kw">case</span> M.lookup (<span class="dt">L</span> lang) lmap <span class="kw">of</span></a>
<a class="sourceLine" id="cb35-10" title="10"> <span class="dt">Just</span> tr <span class="ot">-&gt;</span> <span class="fu">return</span> tr</a>
<a class="sourceLine" id="cb35-11" title="11"> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">return</span> (<span class="st">&quot;NO TRANSLATION FOR &quot;</span> <span class="op">++</span> name)</a>
<a class="sourceLine" id="cb35-12" title="12"> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">return</span> (<span class="st">&quot;NO TRANSLATION FOR &quot;</span> <span class="op">++</span> name)</a></code></pre></div>
<h2 id="conclusion">Conclusion</h2>
<p>The full code is <a href="http://github.com/yogsototh/yblog.git">here</a>. And except from the main file, I use literate Haskell. This way the code should be easier to understand.</p>
<p>If you want to know why I switched from nanoc:</p>
<p>My preceding nanoc website was a bit too messy. So much in fact, that the dependency system recompiled the entire website for any change.</p>
<p>So I had to do something about it. I had two choices:</p>
<ol type="1">
<li>Correct my old code (in Ruby)</li>
<li>Duplicate the core functionalities with Hakyll (in Haskell)</li>
</ol>
<p>I added too much functionalities in my nanoc system. Starting from scratch (almost) remove efficiently a lot of unused crap.</p>
<p>So far I am very happy with the switch. A complete build is about 4x faster. I didnt broke the dependency system this time. As soon as I modify and save the markdown source, I can reload the page in the browser.</p>
<p>I removed a lot of feature thought. Some of them will be difficult to achieve with Hakyll. A typical example:</p>
<p>In nanoc I could take a file like this as source:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode markdown"><code class="sourceCode markdown"><a class="sourceLine" id="cb36-1" title="1"><span class="fu"># Title</span></a>
<a class="sourceLine" id="cb36-2" title="2"></a>
<a class="sourceLine" id="cb36-3" title="3">content</a>
<a class="sourceLine" id="cb36-4" title="4"></a>
<a class="sourceLine" id="cb36-5" title="5">&lt;code file=&quot;foo.hs&quot;&gt;</a>
<a class="sourceLine" id="cb36-6" title="6">main = putStrLn &quot;Cthulhu!&quot;</a>
<a class="sourceLine" id="cb36-7" title="7">&lt;/code&gt;</a></code></pre></div>
<p>And it will create a file <code>foo.hs</code> which could then be downloaded.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb37-1" title="1"><span class="kw">&lt;h1&gt;</span>Title<span class="kw">&lt;/h1&gt;</span></a>
<a class="sourceLine" id="cb37-2" title="2"></a>
<a class="sourceLine" id="cb37-3" title="3"><span class="kw">&lt;p&gt;</span>content<span class="kw">&lt;/p&gt;</span></a>
<a class="sourceLine" id="cb37-4" title="4"></a>
<a class="sourceLine" id="cb37-5" title="5"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;code/foo.hs&quot;</span><span class="kw">&gt;</span>Download foo.hs<span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb37-6" title="6"><span class="kw">&lt;pre&gt;&lt;code&gt;</span>main = putStrLn &quot;Cthulhu!&quot;<span class="kw">&lt;/code&gt;&lt;/pre&gt;</span></a></code></pre></div>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>Nous pouvons aussi ajouter ces métadonnées dans un fichier externe (<code>toto.md.metadata</code>).<a href="#fnref1" class="footnote-back">↩</a></p></li>
</ol>
</section>]]></summary>
</entry>
<entry>
<title>Être correct avec les boutons share</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Social-link-the-right-way/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Social-link-the-right-way/index.html</id>
<published>2013-03-14T00:00:00Z</published>
<updated>2013-03-14T00:00:00Z</updated>
<summary type="html"><![CDATA[<div>
<img src="/Scratch/img/blog/Social-link-the-right-way/main.png" alt="Main image"/>
</div>
<div class="intro">
<p><span class="sc"><abbr title="Trop long; pas lu">tlpl</abbr>: </span> Les boutons des réseaux sociaux traquent vos utilisateurs, ont un design incohérent avec celui de votre site, utilisent des ressources, ralentissent le rendu de vos pages.</p>
<p>Faite les choses bien. Utilisez des liens statiques.</p>
<p>Si vous navez pas envie de lire, copiez et collez simplement le code suivant dans votre <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span>&nbsp;:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb1-1" title="1"><span class="kw">&lt;div</span><span class="ot"> id=</span><span class="st">&quot;sociallinks&quot;</span><span class="kw">&gt;</span></a>
<a class="sourceLine" id="cb1-2" title="2"> <span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://twitter.com/home?status=$url$&quot;</span></a>
<a class="sourceLine" id="cb1-3" title="3"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb1-4" title="4"> <span class="kw">&gt;</span>Tweet this<span class="kw">&lt;/a&gt;</span> -</a>
<a class="sourceLine" id="cb1-5" title="5"> <span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;http://www.facebook.com/sharer/sharer.php?u=$url$&quot;</span></a>
<a class="sourceLine" id="cb1-6" title="6"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb1-7" title="7"> <span class="kw">&gt;</span>Like this<span class="kw">&lt;/a&gt;</span> -</a>
<a class="sourceLine" id="cb1-8" title="8"> <span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://plus.google.com/share?url=$url$&quot;</span></a>
<a class="sourceLine" id="cb1-9" title="9"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb1-10" title="10"> <span class="kw">&gt;</span>Share on G+<span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb1-11" title="11"><span class="kw">&lt;/div&gt;</span></a>
<a class="sourceLine" id="cb1-12" title="12"><span class="kw">&lt;script&gt;</span></a>
<a class="sourceLine" id="cb1-13" title="13">(<span class="kw">function</span>()<span class="op">{</span><span class="va">window</span>.<span class="at">addEventListener</span>(<span class="st">&quot;DOMContentLoaded&quot;</span><span class="op">,</span><span class="kw">function</span>()<span class="op">{</span></a>
<a class="sourceLine" id="cb1-14" title="14"> <span class="kw">var</span> url<span class="op">=</span><span class="va">document</span>.<span class="at">location</span><span class="op">;</span></a>
<a class="sourceLine" id="cb1-15" title="15"> <span class="kw">var</span> links<span class="op">=</span><span class="va">document</span>.<span class="at">getElementById</span>(<span class="st">&quot;sociallinks&quot;</span>)</a>
<a class="sourceLine" id="cb1-16" title="16"> .<span class="at">getElementsByTagName</span>(<span class="st">&#39;a&#39;</span>)<span class="op">;</span></a>
<a class="sourceLine" id="cb1-17" title="17"> <span class="cf">for</span> (<span class="kw">var</span> i<span class="op">=</span><span class="dv">0</span><span class="op">;</span>i<span class="op">!=</span><span class="va">links</span>.<span class="at">length</span><span class="op">;</span>i<span class="op">++</span>)<span class="op">{</span></a>
<a class="sourceLine" id="cb1-18" title="18"> links[i].<span class="at">setAttribute</span>(<span class="st">&quot;href&quot;</span><span class="op">,</span></a>
<a class="sourceLine" id="cb1-19" title="19"> links[i].<span class="va">href</span>.<span class="at">replace</span>(<span class="st">&#39;$url$&#39;</span><span class="op">,</span>url))<span class="op">;}}</span>)<span class="op">}</span>)()<span class="op">;</span></a>
<a class="sourceLine" id="cb1-20" title="20"><span class="kw">&lt;/script&gt;</span></a></code></pre></div>
</div>
<h2 id="the-problem">The problem</h2>
<p>Ever been on a website and want to tweet about it? Fortunately, the website might have a button to help you. But do you really know what this button do?</p>
<p>The “Like”, “Tweet” and “+1” buttons will call a javascript. It will get access to your cookies. It helps the provider of the button to know who you are.</p>
<p>In plain English, the “+1” button will inform Google you are visiting the website, <strong>even if you dont click on “+1”</strong>. The same is true for the “like” button for facebook and the “tweet this” button for twitter.</p>
<p>The problem is not only a privacy issue. In fact (sadly <span class="sc"><abbr title="In my Humble Opinion">imho</abbr></span>) this isnt an issue for most people. These button consume computer ressources. Far more than a simple link. It thus slow down a bit the computer and consume energy. These button could also slow down the rendering of your web page.</p>
<p>Another aspect is their design. Their look and feel is mostly imposed by the provider.</p>
<p>The most problematic aspect in my opinion is to use a third party js on your website. What if tomorrow twitter update their tweet button? If the upgrade break something for only a minority of people, they wont fix it. This could occur anytime without any notification. They just have to add a <code>document.write</code> in their <code>js</code> you call asynchronously and <strong>BAM!</strong> Your website is just an empty blank page. And as you call many external ressources, it can be very difficult to find the origin of the problem.</p>
<p><strong>Using social network buttons:</strong></p>
<ul>
<li>Pros:
<ul>
<li>help user share your website,</li>
<li>can provide a popularity indicator to your users.</li>
</ul></li>
<li>Cons:
<ul>
<li>you help tracking your users,</li>
<li>generally doesnt follow the design of your website,</li>
<li>use more computer ressources,</li>
<li>slow down your website,</li>
<li>executing third party js can break things silently.</li>
</ul></li>
</ul>
<h2 id="solutions">Solutions</h2>
<p>I will provide you two solutions with the following properties:</p>
<ul>
<li>Pros:
<ul>
<li>help user share your website,</li>
<li>doesnt follow your user,</li>
<li>use almost no computer ressource,</li>
<li>doesnt slow down your website,</li>
<li>doesnt execute any third party js on your website.</li>
</ul></li>
<li>Cons:
<ul>
<li>doesnt provide any popularity information.</li>
</ul></li>
</ul>
<p><strong>Solution 1 (no js):</strong></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb2-1" title="1"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://twitter.com/home?status=$url$&quot;</span></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb2-3" title="3"> <span class="kw">&gt;</span>Tweet this<span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb2-4" title="4"></a>
<a class="sourceLine" id="cb2-5" title="5"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;http://www.facebook.com/sharer/sharer.php?u=$url$&quot;</span></a>
<a class="sourceLine" id="cb2-6" title="6"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb2-7" title="7"> <span class="kw">&gt;</span>Like this<span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb2-8" title="8"></a>
<a class="sourceLine" id="cb2-9" title="9"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://plus.google.com/share?url=$url$&quot;</span></a>
<a class="sourceLine" id="cb2-10" title="10"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb2-11" title="11"> <span class="kw">&gt;</span>Share on G+<span class="kw">&lt;/a&gt;</span></a></code></pre></div>
<p>But you have to replace <code>$url$</code> by the current <span class="sc"><abbr title="Uniform Ressource Locator">url</abbr></span>.</p>
<p><strong>Solution 2 (Just copy/paste):</strong></p>
<p>If you dont want to write the <span class="sc"><abbr title="Uniform Ressource Locator">url</abbr></span> yourself, you could use some minimal js:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb3-1" title="1"><span class="kw">&lt;div</span><span class="ot"> id=</span><span class="st">&quot;sociallinks&quot;</span><span class="kw">&gt;</span></a>
<a class="sourceLine" id="cb3-2" title="2"> <span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://twitter.com/home?status=$url$&quot;</span></a>
<a class="sourceLine" id="cb3-3" title="3"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb3-4" title="4"> <span class="kw">&gt;</span>Tweet this<span class="kw">&lt;/a&gt;</span> -</a>
<a class="sourceLine" id="cb3-5" title="5"> <span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;http://www.facebook.com/sharer/sharer.php?u=$url$&quot;</span></a>
<a class="sourceLine" id="cb3-6" title="6"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb3-7" title="7"> <span class="kw">&gt;</span>Like this<span class="kw">&lt;/a&gt;</span> -</a>
<a class="sourceLine" id="cb3-8" title="8"> <span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://plus.google.com/share?url=$url$&quot;</span></a>
<a class="sourceLine" id="cb3-9" title="9"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb3-10" title="10"> <span class="kw">&gt;</span>Share on G+<span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb3-11" title="11"><span class="kw">&lt;/div&gt;</span></a>
<a class="sourceLine" id="cb3-12" title="12"><span class="kw">&lt;script&gt;</span></a>
<a class="sourceLine" id="cb3-13" title="13">(<span class="kw">function</span>()<span class="op">{</span><span class="va">window</span>.<span class="at">addEventListener</span>(<span class="st">&quot;DOMContentLoaded&quot;</span><span class="op">,</span><span class="kw">function</span>()<span class="op">{</span></a>
<a class="sourceLine" id="cb3-14" title="14"> <span class="kw">var</span> url<span class="op">=</span><span class="va">document</span>.<span class="at">location</span><span class="op">;</span></a>
<a class="sourceLine" id="cb3-15" title="15"> <span class="kw">var</span> links<span class="op">=</span><span class="va">document</span>.<span class="at">getElementById</span>(<span class="st">&quot;sociallinks&quot;</span>)</a>
<a class="sourceLine" id="cb3-16" title="16"> .<span class="at">getElementsByTagName</span>(<span class="st">&#39;a&#39;</span>)<span class="op">;</span></a>
<a class="sourceLine" id="cb3-17" title="17"> <span class="cf">for</span> (<span class="kw">var</span> i<span class="op">=</span><span class="dv">0</span><span class="op">;</span>i<span class="op">!=</span><span class="va">links</span>.<span class="at">length</span><span class="op">;</span>i<span class="op">++</span>)<span class="op">{</span></a>
<a class="sourceLine" id="cb3-18" title="18"> links[i].<span class="at">setAttribute</span>(<span class="st">&quot;href&quot;</span><span class="op">,</span></a>
<a class="sourceLine" id="cb3-19" title="19"> links[i].<span class="va">href</span>.<span class="at">replace</span>(<span class="st">&#39;$url$&#39;</span><span class="op">,</span>url))<span class="op">;}}</span>)<span class="op">}</span>)()<span class="op">;</span></a>
<a class="sourceLine" id="cb3-20" title="20"><span class="kw">&lt;/script&gt;</span></a></code></pre></div>
<p>Here is the result:</p>
<div class="nostar" style="text-align:center">
<div id="sociallinks">
<p><a href="https://twitter.com/home?status=$url$"
target="_blank" rel="noopener noreferrer nofollow"
>Tweet this</a> - <a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
target="_blank" rel="noopener noreferrer nofollow"
>Like this</a> - <a href="https://plus.google.com/share?url=$url$"
target="_blank" rel="noopener noreferrer nofollow"
>Share on G+</a></p>
</div>
<script>
(function(){window.addEventListener("DOMContentLoaded",function(){
var url=document.location;
var links=document.getElementById("sociallinks")
.getElementsByTagName('a');
for (var i=0;i!=links.length;i++){
links[i].setAttribute("href",
links[i].href.replace('$url$',url));}})})();
</script>
</div>
<h2 id="good-looking-solutions">Good looking solutions</h2>
<p>If you dont want just text but nice icons. You have many choices:</p>
<ul>
<li>Use images <code>&lt;img src="..."/&gt;</code> in the links.</li>
<li>Use icon fonts</li>
</ul>
<p>As the first solution is pretty straightforward, Ill explain the second one.</p>
<ol type="1">
<li>Download the icon font <a href="http://blog.martianwabbit.com/post/4344642365.html">here</a></li>
<li>put the font file(s) at some place (here fonts/social_font.ttf relatively to your <span class="sc">css</span> file)</li>
<li>Add this to your <span class="sc">css</span></li>
</ol>
<div class="sourceCode" id="cb4"><pre class="sourceCode css"><code class="sourceCode css"><a class="sourceLine" id="cb4-1" title="1"><span class="im">@font-face</span></a>
<a class="sourceLine" id="cb4-2" title="2"> font-family: &#39;social&#39;</a>
<a class="sourceLine" id="cb4-3" title="3"> src: url(&#39;fonts/social_font.ttf&#39;) format(&#39;truetype&#39;)</a>
<a class="sourceLine" id="cb4-4" title="4"> font-weight: normal</a>
<a class="sourceLine" id="cb4-5" title="5"> font-style: normal</a>
<a class="sourceLine" id="cb4-6" title="6">.social</a>
<a class="sourceLine" id="cb4-7" title="7"> font-family: social</a></code></pre></div>
<p>Now add this to your <span class="sc"><abbr title="HyperText Markup Language">html</abbr></span>:</p>
<p><strong>Solution 1 (without js):</strong></p>
<div class="sourceCode" id="cb5"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb5-1" title="1"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://twitter.com/home?status=$url$&quot;</span></a>
<a class="sourceLine" id="cb5-2" title="2"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb5-3" title="3"><span class="ot"> class=</span><span class="st">&quot;social&quot;</span><span class="kw">&gt;</span><span class="dv">&amp;#116;</span><span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb5-4" title="4">·</a>
<a class="sourceLine" id="cb5-5" title="5"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;http://www.facebook.com/sharer/sharer.php?u=$url$&quot;</span></a>
<a class="sourceLine" id="cb5-6" title="6"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb5-7" title="7"><span class="ot"> class=</span><span class="st">&quot;social&quot;</span><span class="kw">&gt;</span><span class="dv">&amp;#0096;</span><span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb5-8" title="8">·</a>
<a class="sourceLine" id="cb5-9" title="9"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://plus.google.com/share?url=$url$&quot;</span></a>
<a class="sourceLine" id="cb5-10" title="10"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb5-11" title="11"><span class="ot"> class=</span><span class="st">&quot;social&quot;</span><span class="kw">&gt;</span><span class="dv">&amp;#0103;</span><span class="kw">&lt;/a&gt;</span></a></code></pre></div>
<p><strong>Solution 2 (same with a bit more js):</strong></p>
<div class="sourceCode" id="cb6"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb6-1" title="1"><span class="kw">&lt;div</span><span class="ot"> id=</span><span class="st">&quot;sociallinksunicode&quot;</span><span class="kw">&gt;</span></a>
<a class="sourceLine" id="cb6-2" title="2"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://twitter.com/home?status=$url$&quot;</span></a>
<a class="sourceLine" id="cb6-3" title="3"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb6-4" title="4"><span class="ot"> class=</span><span class="st">&quot;social&quot;</span><span class="kw">&gt;</span><span class="dv">&amp;#116;</span><span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb6-5" title="5">·</a>
<a class="sourceLine" id="cb6-6" title="6"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;http://www.facebook.com/sharer/sharer.php?u=$url$&quot;</span></a>
<a class="sourceLine" id="cb6-7" title="7"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb6-8" title="8"><span class="ot"> class=</span><span class="st">&quot;social&quot;</span><span class="kw">&gt;</span><span class="dv">&amp;#0096;</span><span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb6-9" title="9">·</a>
<a class="sourceLine" id="cb6-10" title="10"><span class="kw">&lt;a</span><span class="ot"> href=</span><span class="st">&quot;https://plus.google.com/share?url=$url$&quot;</span></a>
<a class="sourceLine" id="cb6-11" title="11"><span class="ot"> target=</span><span class="st">&quot;_blank&quot;</span><span class="ot"> rel=</span><span class="st">&quot;noopener noreferrer nofollow&quot;</span></a>
<a class="sourceLine" id="cb6-12" title="12"><span class="ot"> class=</span><span class="st">&quot;social&quot;</span><span class="kw">&gt;</span><span class="dv">&amp;#0103;</span><span class="kw">&lt;/a&gt;</span></a>
<a class="sourceLine" id="cb6-13" title="13"><span class="kw">&lt;/div&gt;</span></a>
<a class="sourceLine" id="cb6-14" title="14"><span class="kw">&lt;script&gt;</span></a>
<a class="sourceLine" id="cb6-15" title="15">(<span class="kw">function</span>()<span class="op">{</span><span class="va">window</span>.<span class="at">addEventListener</span>(<span class="st">&quot;DOMContentLoaded&quot;</span><span class="op">,</span><span class="kw">function</span>()<span class="op">{</span></a>
<a class="sourceLine" id="cb6-16" title="16"> <span class="kw">var</span> url<span class="op">=</span><span class="va">document</span>.<span class="at">location</span><span class="op">;</span></a>
<a class="sourceLine" id="cb6-17" title="17"> <span class="kw">var</span> links<span class="op">=</span><span class="va">document</span>.<span class="at">getElementById</span>(<span class="st">&quot;sociallinksunicode&quot;</span>)</a>
<a class="sourceLine" id="cb6-18" title="18"> .<span class="at">getElementsByTagName</span>(<span class="st">&#39;a&#39;</span>)<span class="op">;</span></a>
<a class="sourceLine" id="cb6-19" title="19"> <span class="cf">for</span> (<span class="kw">var</span> i<span class="op">=</span><span class="dv">0</span><span class="op">;</span>i<span class="op">!=</span><span class="va">links</span>.<span class="at">length</span><span class="op">;</span>i<span class="op">++</span>)<span class="op">{</span></a>
<a class="sourceLine" id="cb6-20" title="20"> links[i].<span class="at">setAttribute</span>(<span class="st">&quot;href&quot;</span><span class="op">,</span></a>
<a class="sourceLine" id="cb6-21" title="21"> links[i].<span class="va">href</span>.<span class="at">replace</span>(<span class="st">&#39;$url$&#39;</span><span class="op">,</span>url))<span class="op">;}}</span>)<span class="op">}</span>)()<span class="op">;</span></a>
<a class="sourceLine" id="cb6-22" title="22"><span class="kw">&lt;/script&gt;</span></a></code></pre></div>
<p>Here is the result:</p>
<div class="nostar" style="font-size: 2em; text-align: center;">
<div id="sociallinksunicode">
<p><a href="https://twitter.com/home?status=$url$"
target="_blank" rel="noopener noreferrer nofollow"
class="social">t</a> · <a href="http://www.facebook.com/sharer/sharer.php?u=$url$"
target="_blank" rel="noopener noreferrer nofollow"
class="social">`</a> · <a href="https://plus.google.com/share?url=$url$"
target="_blank" rel="noopener noreferrer nofollow"
class="social">g</a></p>
</div>
<script>
(function(){window.addEventListener("DOMContentLoaded",function(){
var url=document.location;
var links=document.getElementById("sociallinksunicode")
.getElementsByTagName('a');
for (var i=0;i!=links.length;i++){
links[i].setAttribute("href",
links[i].href.replace('$url$',url));}})})();
</script>
</div>
<h2 id="conclusion">Conclusion</h2>
<ol type="1">
<li>You get your design back,</li>
<li>You stop to help tracking people,</li>
<li>You use less computer ressources and more generally power ressources which is good for the planet,</li>
<li>Your web pages will load faster.</li>
</ol>
<p><em>ps</em>: On my personal website I continue to use Google analytics. Therefore, Google (and only Google, not facebook nor twitter) can track you here. But I might change this in the future.</p>]]></summary>
</entry>
<entry>
<title>Category Theory Presentation</title>
<link href="http://yannesposito.com/Scratch/fr/blog/Category-Theory-Presentation/index.html" />
<id>http://yannesposito.com/Scratch/fr/blog/Category-Theory-Presentation/index.html</id>
<published>2012-12-12T00:00:00Z</published>
<updated>2012-12-12T00:00:00Z</updated>
<summary type="html"><![CDATA[<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-hask-endofunctor.png" alt="Cateogry of Hask's endofunctors"/>
<p>Yesterday I was happy to make a presentation about Category Theory at <a href="http://www.meetup.com/riviera-scala-clojure">Riviera Scala Clojure Meetup</a> (note I used only Haskell for my examples).</p>
<ul><li><a href="http://yogsototh.github.io/Category-Theory-Presentation/categories.html">Click here to go to the HTML presentation.</a>
</li><li><a href="http://yogsototh.github.io/Category-Theory-Presentation/categories.pdf">Click Here to download the PDF slides (<span style="text-transform: uppercase">L<sup style="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<sub style="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span> not rendered properly)</a>
</li></ul>
<p>If you don't want to read them through an HTML presentations framework or downloading a big PDF
just continue to read as a standard web page.
</p>
<div style="display:none">
\(\newcommand{\F}{\mathbf{F}}\)
\(\newcommand{\E}{\mathbf{E}}\)
\(\newcommand{\C}{\mathcal{C}}\)
\(\newcommand{\D}{\mathcal{D}}\)
\(\newcommand{\id}{\mathrm{id}}\)
\(\newcommand{\ob}[1]{\mathrm{ob}(#1)}\)
\(\newcommand{\hom}[1]{\mathrm{hom}(#1)}\)
\(\newcommand{\Set}{\mathbf{Set}}\)
\(\newcommand{\Mon}{\mathbf{Mon}}\)
\(\newcommand{\Vec}{\mathbf{Vec}}\)
\(\newcommand{\Grp}{\mathbf{Grp}}\)
\(\newcommand{\Rng}{\mathbf{Rng}}\)
\(\newcommand{\ML}{\mathbf{ML}}\)
\(\newcommand{\Hask}{\mathbf{Hask}}\)
\(\newcommand{\Cat}{\mathbf{Cat}}\)
\(\newcommand{\fmap}{\mathtt{fmap}}\)
</div>
<section class="slide" style="text-align: center;">
<h1 style="position: relative;">Category Theory <span class="and">&amp;</span> Programming</h1>
<div><em class="base01">for</em> <a href="http://www.meetup.com/riviera-scala-clojure">Rivieria Scala Clojure</a> (Note this presentation uses Haskell)</div>
<author><em class="base01">by</em> <a href="http://yannesposito.com">Yann Esposito</a></author>
<div style="font-size:.8em; margin: 5em auto">
<twitter>
<a href="http://twitter.com/yogsototh">@yogsototh</a>,
</twitter>
<googleplus>
<a href="https://plus.google.com/117858550730178181663">+yogsototh</a>
</googleplus>
</div>
<div class="flush"></div></section>
<section class="slide">
<h2>Plan</h2>
<ul style="font-size: 2em; font-weight:bold">
<li><span class="orange">General overview</li>
<li>Definitions</li>
<li>Applications</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="not-really-about-cat-glory">Not really about: Cat <span class="and">&amp;</span> glory</h2>
<figure>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/categlory.jpg" alt="Cat n glory" /> <figcaption>credit to Tokuhiro Kawai (川井徳寛)</figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2 id="general-overview">General Overview</h2>
<div style="float:right; width: 18%">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/eilenberg.gif" alt="Samuel Eilenberg"/> <img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/maclaine.jpg" alt="Saunders Mac Lane"/>
</div>
<p><em>Recent Math Field</em><br />1942-45, Samuel Eilenberg <span class="and">&amp;</span> Saunders Mac Lane</p>
<p>Certainly one of the more abstract branches of math</p>
<ul>
<li><em>New math foundation</em><br /> formalism abstraction, package entire theory<sup>★</sup></li>
<li><em>Bridge between disciplines</em><br /> Physics, Quantum Physics, Topology, Logic, Computer Science<sup>☆</sup></li>
</ul>
<p class="base01" style="border-top: solid 1px; width: 70%; font-size: 0.7em">
★: <a href="http://www.math.harvard.edu/~mazur/preprints/when_is_one.pdf">When is one thing equal to some other thing?, Barry Mazur, 2007</a><br/> ☆: <a href="http://math.ucr.edu/home/baez/rosetta.pdf">Physics, Topology, Logic and Computation: A Rosetta Stone, John C. Baez, Mike Stay, 2009</a>
</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="from-a-programmer-perspective">From a Programmer perspective</h2>
<blockquote>
<p>Category Theory is a new language/framework for Math</p>
</blockquote>
<ul>
<li>Another way of thinking</li>
<li>Extremely efficient for generalization</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="math-programming-relation">Math Programming relation</h2>
<img class="right" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/buddha.gif" alt="Buddha Fractal"/>
<p>Programming <em><span class="orange">is</span></em> doing Math</p>
<p>Strong relations between type theory and category theory.</p>
<p>Not convinced?<br />Certainly a <em>vocabulary</em> problem.</p>
<p>One of the goal of Category Theory is to create a <em>homogeneous vocabulary</em> between different disciplines.</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="vocabulary">Vocabulary</h2>
<img class="right" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mindblown.gif" alt="mind blown"/>
<p>Math vocabulary used in this presentation:</p>
<blockquote style="width:55%">
<p>Category, Morphism, Associativity, Preorder, Functor, Endofunctor, Categorial property, Commutative diagram, Isomorph, Initial, Dual, Monoid, Natural transformation, Monad, Klesli arrows, κατα-morphism, ...</p>
</blockquote>
<div class="flush"></div></section>
<section class="slide">
<h2 id="programmer-translation">Programmer Translation</h2>
<img class="right" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/readingcat.jpg" alt="lolcat"/>
<table style="width:50%">
<tr><th>
Mathematician
</th><th>
Programmer
</th></tr>
<tr><td>
Morphism
</td><td>
Arrow
</td></tr>
<tr><td>
Monoid
</td><td>
String-like
</td></tr>
<tr><td>
Preorder
</td><td>
Acyclic graph
</td></tr>
<tr><td>
Isomorph
</td><td>
The same
</td></tr>
<tr><td>
Natural transformation
</td><td>
rearrangement function
</td></tr>
<tr><td>
Funny Category
</td><td>
LOLCat
</td></tr>
</table>
<div class="flush"></div></section>
<section class="slide">
<h2>Plan</h2>
<ul style="font-size: 2em; font-weight: bold">
<li>General overview</li>
<li> <span class="orange">Definitions</span>
<ul class="base01" style="border-left: 2px solid; padding-left: 1em; font-size: .6em; float: right; font-weight: bold; margin: 0 0 0 1em; width: 17em">
<li>Category</li>
<li>Intuition</li>
<li>Examples</li>
<li>Functor</li>
<li>Examples</li>
</ul>
</li>
<li>Applications</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Category</h2>
<p>A way of representing <strong><em>things</em></strong> and <strong><em>ways to go between things</em></strong>.</p>
<p> A Category \(\mathcal{C}\) is defined by:</p>
<ul>
<li> <em>Objects <span class="orange">\(\ob{C}\)</span></em>,</li>
<li> <em>Morphisms <span class="orange">\(\hom{C}\)</span></em>,</li>
<li> a <em>Composition law <span class="orange">(∘)</span></em></li>
<li> obeying some <em>Properties</em>.</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Category: Objects</h2>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/objects.png" alt="objects" />
<p>\(\ob{\mathcal{C}}\) is a collection</p>
<div class="flush"></div></section>
<section class="slide">
<h2>Category: Morphisms</h2>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/morphisms.png" alt="morphisms"/>
<p>\(A\) and \(B\) objects of \(\C\)<br/>
\(\hom{A,B}\) is a collection of morphisms<br/>
\(f:A→B\) denote the fact \(f\) belongs to \(\hom{A,B}\)</p>
<p>\(\hom{\C}\) the collection of all morphisms of \(\C\)</p>
<div class="flush"></div></section>
<section class="slide">
<h2>Category: Composition</h2>
<p>Composition (∘): associate to each couple \(f:A→B, g:B→C\)
$$g∘f:A\rightarrow C$$
</p>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/composition.png" alt="composition"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Category laws: neutral element</h2>
<p>for each object \(X\), there is an \(\id_X:X→X\),<br/>
such that for each \(f:A→B\):</p>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/identity.png" alt="identity"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Category laws: Associativity</h2>
<p> Composition is associative:</p>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/associativecomposition.png" alt="associative composition"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Commutative diagrams</h2>
<p>Two path with the same source and destination are equal.</p>
<figure class="left" style="max-width: 40%;margin-left: 5%;">
<img
src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/commutative-diagram-assoc.png"
alt="Commutative Diagram (Associativity)"/>
<figcaption>
\((h∘g)∘f = h∘(g∘f) \)
</figcaption>
</figure>
<figure class="right" style="max-width:31%;margin-right: 10%;">
<img
src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/commutative-diagram-id.png"
alt="Commutative Diagram (Identity law)"/>
<figcaption>
\(id_B∘f = f = f∘id_A \)
</figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2>Question Time!</h2>
<figure style="width:70%; margin:0 auto">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/batquestion.jpg" width="100%"/>
<figcaption>
<em>- French-only joke -</em>
</figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2>Can this be a category?</h2>
<p>\(\ob{\C},\hom{\C}\) fixed, is there a valid ∘?</p>
<figure class="left">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-example1.png" alt="Category example 1"/>
<figcaption class="slide">
<span class="green">YES</span>
</figcaption>
</figure>
<figure class="left">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-example2.png" alt="Category example 2"/>
<figcaption class="slide">
no candidate for \(g∘f\)
<br/><span class="red">NO</span>
</figcaption>
</figure>
<figure class="left">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-example3.png" alt="Category example 3"/>
<figcaption class="slide">
<span class="green">YES</span>
</figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2>Can this be a category?</h2>
<figure class="left">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-example4.png" alt="Category example 4"/>
<figcaption class="slide">
no candidate for \(f:C→B\)
<br/><span class="red">NO</span>
</figcaption>
</figure>
<figure class="right" style="min-width: 50%">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-example5.png" alt="Category example 5"/>
<figcaption class="slide">
\((h∘g)∘f=\id_B∘f=f\)<br/>
\(h∘(g∘f)=h∘\id_A=h\)<br/>
but \(h≠f\)<br/>
<span class="red">NO</span>
</figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2>Categories Examples</h2>
<figure style="width:70%; margin:0 auto">
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/basket_of_cats.jpg" alt="Basket of cats"/>
<figcaption>
<em>- Basket of Cats -</em>
</figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2>Category \(\Set\)</h2>
<ul>
<li> \(\ob{\Set}\) are <em>all</em> the sets</li>
<li> \(\hom{E,F}\) are <em>all</em> functions from \(E\) to \(F\)</li>
<li> ∘ is functions composition </li>
</ul>
<ul class="slide">
<li>\(\ob{\Set}\) is a proper class ; not a set</li>
<li>\(\hom{E,F}\) is a set</li>
<li>\(\Set\) is then a <em>locally <b>small</b> category</em></li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Categories Everywhere?</h2>
<img class="right" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/cats-everywhere.jpg" alt="Cats everywhere"/>
<ul>
<li>\(\Mon\): (monoids, monoid morphisms,∘)</li>
<li>\(\Vec\): (Vectorial spaces, linear functions,∘)</li>
<li>\(\Grp\): (groups, group morphisms,∘)</li>
<li>\(\Rng\): (rings, ring morphisms,∘)</li>
<li>Any deductive system <i>T</i>: (theorems, proofs, proof concatenation)</li>
<li>\( \Hask\): (Haskell types, functions, <code>(.)</code> )</li>
<li>...</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Smaller Examples</h2>
<h3>Strings</h3>
<img class="right" style="max-width:17%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/strings.png" alt="Monoids are one object categories"/>
<ul>
<li> \(\ob{Str}\) is a singleton </li>
<li> \(\hom{Str}\) each string </li>
<li> ∘ is concatenation <code>(++)</code> </li>
</ul>
<ul>
<li> <code>"" ++ u = u = u ++ ""</code> </li>
<li> <code>(u ++ v) ++ w = u ++ (v ++ w)</code> </li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Finite Example?</h2>
<h3>Graph</h3>
<figure class="right" style="max-width:40%" >
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/graph-category.png" alt="Each graph is a category"/>
</figure>
<ul>
<li> \(\ob{G}\) are vertices</li>
<li> \(\hom{G}\) each path</li>
<li> ∘ is path concatenation</li>
</ul>
<ul><li>\(\ob{G}=\{X,Y,Z\}\),
</li><li>\(\hom{G}=\{ε,α,β,γ,αβ,βγ,...\}\)
</li><li>\(αβ∘γ=αβγ\)
</li></ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Number construction</h2>
<h3>Each Numbers as a whole category</h3>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/numbers.png" alt="Each number as a category"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Degenerated Categories: Monoids</h2>
<img class="right" style="max-width:17%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/monoid.png" alt="Monoids are one object categories"/>
<p>Each Monoid \((M,e,⊙): \ob{M}=\{∙\},\hom{M}=M,\circ = ⊙\)</p>
<p class="orange">Only one object.</p>
<p>Examples:</p>
<ul><li><code>(Integer,0,+)</code>, <code>(Integer,1,*)</code>,
</li><li><code>(Strings,"",++)</code>, for each <code>a</code>, <code>([a],[],++)</code>
</li></ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Degenerated Categories: Preorders \((P,≤)\)</h2>
<ul><li>\(\ob{P}={P}\),
</li><li>\(\hom{x,y}=\{x≤y\} ⇔ x≤y\),
</li><li>\((y≤z) \circ (x≤y) = (x≤z) \)
</li></ul>
<p><em class="orange">At most one morphism between two objects.</em></p>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/preorder.png" alt="preorder category"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Degenerated Categories: Discrete Categories</h2>
<img class="right" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/set.png" alt="Any set can be a category"/>
<h3>Any Set</h3>
<p>Any set \(E: \ob{E}=E, \hom{x,y}=\{x\} ⇔ x=y \)</p>
<p class="orange">Only identities</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="choice">Choice</h2>
<p>The same object can be seen in many different way as a category.</p>
<p>You can choose what are object, morphisms and composition.</p>
<p>ex: <strong>Str</strong> and discrete(Σ<sup>*</sup>)</p>
<div class="flush"></div></section>
<section class="slide">
<h2 class="base1">Categorical Properties</h2>
<p class="base1">Any property which can be expressed in term of category, objects, morphism and composition.</p>
<ul><li> <em class="orange">Dual</em>: \(\D\) is \(\C\) with reversed morphisms.
</li><li> <em class="orange">Initial</em>: \(Z\in\ob{\C}\) s.t. \(∀Y∈\ob{\C}, \#\hom{Z,Y}=1\)
<br/> Unique ("up to isormophism")
</li><li> <em class="orange">Terminal</em>: \(T\in\ob{\C}\) s.t. \(T\) is initial in the dual of \(\C\)
</li><li> <em class="orange">Functor</em>: structure preserving mapping between categories
</li><li> ...
</li></ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="isomorph">Isomorph</h2>
<p><img class="right" alt="isomorph cats" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/isomorph-cats.jpg" /> <em class="orange">isomorphism</em>: \(f:A→B\) which can be &quot;undone&quot; <em>i.e.</em><br />\(∃g:B→A\), \(g∘f=id_A\) <span class="and">&amp;</span> \(f∘g=id_B\)<br />in this case, \(A\) <span class="and">&amp;</span> \(B\) are <em class="orange">isomorphic</em>.</p>
<p><span class="orange">A≌B</span> means A and B are essentially the same.<br />In Category Theory, <span class="orange">=</span> is in fact mostly <span class="orange">≌</span>.<br />For example in commutative diagrams.</p>
<div class="flush"></div></section>
<section class="slide">
<h2>Functor</h2>
<p> A functor is a mapping between two categories.
Let \(\C\) and \(\D\) be two categories.
A <em>functor</em> <span class="orange">\(\F\)</span> from <span class="blue">\(\C\)</span> to <span class="green">\(\D\)</span>:</p>
<ul>
<li> Associate objects: <span class="backblue">\(A\in\ob{\C}\)</span> to <span class="backgreen">\(\F(A)\in\ob{\D}\)</span> </li>
<li> Associate morphisms: <span class="backblue">\(f:A\to B\)</span> to <span class="backgreen">\(\F(f) : \F(A) \to \F(B)\)</span>
such that
<ul>
<li>\( \F (\)<span class="backblue blue">\(\id_X\)</span>\()= \)<span class="backgreen"><span class="green">\(\id\)</span>\(\vphantom{\id}_{\F(}\)<span class="blue">\(\vphantom{\id}_X\)</span>\(\vphantom{\id}_{)} \)</span>,</li>
<li>\( \F (\)<span class="backblue blue">\(g∘f\)</span>\()= \)<span class="backgreen">\( \F(\)<span class="blue">\(g\)</span>\() \)<span class="green">\(\circ\)</span>\( \F(\)<span class="blue">\(f\)</span>\() \)</span></li>
</ul>
</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Functor Example (ob → ob)</h2>
<img width="65%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/functor.png" alt="Functor"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Functor Example (hom → hom)</h2>
<img width="65%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/functor-morphism.png" alt="Functor"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Functor Example</h2>
<img width="65%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/functor-morphism-color.png" alt="Functor"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Endofunctors</h2>
<p>An <em>endofunctor</em> for \(\C\) is a functor \(F:\C→\C\).</p>
<img width="75%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/endofunctor.png" alt="Endofunctor"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Category of Categories</h2>
<img style="min-width:43%; width: 43%" class="right" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/fractalcat.jpg" />
<p>Categories and functors form a category: \(\Cat\)</p>
<ul><li>\(\ob{\Cat}\) are categories
</li><li>\(\hom{\Cat}\) are functors
</li><li>∘ is functor composition
</li></ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Plan</h2>
<ul style="font-size: 2em; font-weight:bold">
<li>General overview</li>
<li>Definitions</li>
<li><span class="orange">Applications
<ul class="base01" style="border-left: 2px solid; padding-left: 1em; font-size: .6em; float: right; font-weight: bold; margin: -4em 0 0 1em; width: 17em">
<li>\(\Hask\) category
</li><li> Functors
</li><li> Natural transformations
</li><li> Monads
</li><li> κατα-morphisms
</li></ul>
</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Hask</h2>
<p>Category \(\Hask\):</p>
<img class="right" style="max-width:30%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/hask.png" alt="Haskell Category Representation"/>
<ul><li>
\(\ob{\Hask} = \) Haskell types
</li><li>
\(\hom{\Hask} = \) Haskell functions
</li><li>
∘ = <code>(.)</code> Haskell function composition
</li></ul>
<p>Forget glitches because of <code>undefined</code>.</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="haskell-kinds">Haskell Kinds</h2>
<p>In Haskell some types can take type variable(s). Typically: <code>[a]</code>.</p>
<p>Types have <em>kinds</em>; The kind is to type what type is to function. Kind are the types for types (so meta).</p>
<pre><code>Int, Char :: *
[], Maybe :: * -&gt; *
(,), (-&gt;) :: * -&gt; * -&gt; *
[Int], Maybe Char, Maybe [Int] :: *</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="haskell-types">Haskell Types</h2>
<p>Sometimes, the type determine a lot about the function<sup>★</sup>:</p>
<pre class="haskell"><code>fst :: (a,b) -> a -- Only one choice
snd :: (a,b) -> b -- Only one choice
f :: a -> [a] -- Many choices
-- Possibilities: f x=[], or [x], or [x,x] or [x,...,x]
? :: [a] -> [a] -- Many choices
-- can only rearrange: duplicate/remove/reorder elements
-- for example: the type of addOne isn't [a] -> [a]
addOne l = map <span class="red">(+1)</span> l
-- The (+1) force 'a' to be a Num.</code></pre>
<p>
<p><span class="small base01">★:<a href="http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf">Theorems for free!, Philip Wadler, 1989</a></span></p>
<div class="flush"></div></section>
<section class="slide">
<h2>Haskell Functor vs \(\Hask\) Functor</h2>
<p>A Haskell Functor is a type <code>F :: * -> *</code> which belong to the type class <code>Functor</code> ; thus instantiate
<code>fmap :: (a -> b) -> (F a -> F b)</code>.
<p><span style="visibility:hidden"><span class="and">&amp;</span></span> <code>F</code>: \(\ob{\Hask}→\ob{\Hask}\)<br/> <span class="and">&amp;</span> <code>fmap</code>: \(\hom{\Hask}→\hom{\Hask}\)
<p>The couple <code>(F,fmap)</code> is a \(\Hask\)'s functor if for any <code>x :: F a</code>:</p>
<ul><li><code>fmap id x = x</code>
</li><li><code>fmap (f.g) x= (fmap f . fmap g) x</code>
</li></ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Haskell Functors Example: Maybe</h2>
<pre class="haskell"><code>data Maybe a = Just a | Nothing
instance Functor Maybe where
fmap :: (a -> b) -> (Maybe a -> Maybe b)
fmap f (Just a) = Just (f a)
fmap f Nothing = Nothing</code></pre>
<pre class="haskell"><code>fmap (+1) (Just 1) == Just 2
fmap (+1) Nothing == Nothing
fmap head (Just [1,2,3]) == Just 1</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2>Haskell Functors Example: List</h2>
<pre class="haskell"><code>instance Functor ([]) where
fmap :: (a -> b) -> [a] -> [b]
fmap = map</pre></code>
<pre class="haskell"><code>fmap (+1) [1,2,3] == [2,3,4]
fmap (+1) [] == []
fmap head [[1,2,3],[4,5,6]] == [1,4]</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="haskell-functors-for-the-programmer">Haskell Functors for the programmer</h2>
<p><code>Functor</code> is a type class used for types that can be mapped over.</p>
<ul>
<li>Containers: <code>[]</code>, Trees, Map, HashMap...</li>
<li>&quot;Feature Type&quot;:
<ul>
<li><code>Maybe a</code>: help to handle absence of <code>a</code>.<br />Ex: <code>safeDiv x 0 ⇒ Nothing</code></li>
<li><code>Either String a</code>: help to handle errors<br />Ex: <code>reportDiv x 0 ⇒ Left &quot;Division by 0!&quot;</code></li>
</ul></li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Haskell Functor intuition</h2>
<p>Put normal function inside a container. Ex: list, trees...<p>
<img width="70%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/boxfunctor.png" alt="Haskell Functor as a box play"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Haskell Functor properties</h2>
<p>Haskell Functors are:</p>
<ul><li><em>endofunctors</em> ; \(F:\C→\C\) here \(\C = \Hask\),
</li><li>a couple <b>(Object,Morphism)</b> in \(\Hask\).
</li></ul>
<div class="flush"></div></section>
<section class="slide">
<h2>Functor as boxes</h2>
<p>Haskell functor can be seen as boxes containing all Haskell types and functions.
Haskell types look like a fractal:</p>
<img width="70%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/hask-endofunctor.png" alt="Haskell functor representation"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Functor as boxes</h2>
<p>Haskell functor can be seen as boxes containing all Haskell types and functions.
Haskell types look like a fractal:</p>
<img width="70%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/hask-endofunctor-objects.png" alt="Haskell functor representation"/>
<div class="flush"></div></section>
<section class="slide">
<h2>Functor as boxes</h2>
<p>Haskell functor can be seen as boxes containing all Haskell types and functions.
Haskell types look like a fractal:</p>
<img width="70%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/hask-endofunctor-morphisms.png" alt="Haskell functor representation"/>
<div class="flush"></div></section>
<section class="slide">
<h2 id="non-haskell-hasks-functors">&quot;Non Haskell&quot; Hask's Functors</h2>
<p>A simple basic example is the \(id_\Hask\) functor. It simply cannot be expressed as a couple (<code>F</code>,<code>fmap</code>) where</p>
<ul>
<li><code>F::* -&gt; *</code></li>
<li><code>fmap :: (a -&gt; b) -&gt; (F a) -&gt; (F b)</code></li>
</ul>
<p>Another example:</p>
<ul>
<li>F(<code>T</code>)=<code>Int</code></li>
<li>F(<code>f</code>)=<code>\_-&gt;0</code></li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="also-functor-inside-hask">Also Functor inside \(\Hask\)</h2>
<p>\(\mathtt{[a]}∈\ob{\Hask}\)</code> but is also a category. Idem for <code>Int</code>.</p>
<p><code>length</code> is a Functor from the category <code>[a]</code> to the category <code>Int</code>:</p>
<ul class="left" style="max-width:40%">
<li>\(\ob{\mathtt{[a]}}=\{∙\}\)</li>
<li>\(\hom{\mathtt{[a]}}=\mathtt{[a]}\)</li>
<li>\(∘=\mathtt{(++)}\)</li>
</ul>
<p class="left" style="margin:2em 3em">⇒</p>
<ul class="left" style="max-width:40%">
<li>\(\ob{\mathtt{Int}}=\{∙\}\)</li>
<li>\(\hom{\mathtt{Int}}=\mathtt{Int}\)</li>
<li>\(∘=\mathtt{(+)}\)</li>
</ul>
<div class="flush"></div>
<ul><li>id: <code>length [] = 0</code>
</li><li>comp: <code>length (l ++ l') = (length l) + (length l')</code>
</li></ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="category-of-hask-endofunctors">Category of \(\Hask\) Endofunctors</h2>
<img width="50%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-hask-endofunctor.png" alt="Category of Hask endofunctors" />
<div class="flush"></div></section>
<section class="slide">
<h2 id="category-of-functors">Category of Functors</h2>
<p>If \(\C\) is <em>small</em> (\(\hom{\C}\) is a set). All functors from \(\C\) to some category \(\D\) form the category \(\mathrm{Func}(\C,\D)\).</p>
<ul>
<li>\(\ob{\mathrm{Func}(\C,\D)}\): Functors \(F:\C→\D\)</li>
<li>\(\hom{\mathrm{Func}(\C,\D)}\): <em>natural transformations</em></li>
<li>∘: Functor composition</li>
</ul>
<p>\(\mathrm{Func}(\C,\C)\) is the category of endofunctors of \(\C\).</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="natural-transformations">Natural Transformations</h2>
<p>Let \(F\) and \(G\) be two functors from \(\C\) to \(\D\).</p>
<p><img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/natural-transformation.png" alt="Natural transformation commutative diagram" class="right"/> <em>A natural transformation:</em> familly η ; \(η_X\in\hom{\D}\) for \(X\in\ob{\C}\) s.t.</p>
<p>ex: between Haskell functors; <code>F a -&gt; G a</code><br />Rearragement functions only.</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="natural-transformation-examples-14">Natural Transformation Examples (1/4)</h2>
<pre><code class="haskell small">data List a = Nil | Cons a (List a)
toList :: [a] -> List a
toList [] = Nil
toList (x:xs) = Cons x (toList xs)</code></pre>
<p><code>toList</code> is a natural transformation. It is also a morphism from <code>[]</code> to <code>List</code> in the Category of \(\Hask\) endofunctors.</p>
<img style="float:left;width:30%;margin-left: 1em;" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/nattrans-list-tree.png" alt="natural transformation commutative diagram"/>
<figure style="float:right;width:50%">
<img style="width:40%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/list-tree-endofunctor-morphism.png" alt="natural transformation commutative diagram"/>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2 id="natural-transformation-examples-24">Natural Transformation Examples (2/4)</h2>
<pre><code class="haskell small">data List a = Nil | Cons a (List a)
toHList :: List a -> [a]
toHList Nil = []
toHList (Cons x xs) = x:toHList xs</code></pre>
<p><code>toHList</code> is a natural transformation. It is also a morphism from <code>List</code> to <code>[]</code> in the Category of \(\Hask\) endofunctors.</p>
<img style="float:left;width:30%;margin-left:1em" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/nattrans-tree-list.png" alt="natural transformation commutative diagram"/>
<figure style="float:right;width:50%">
<img style="width:40%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/tree-list-endofunctor-morphism.png" alt="natural transformation commutative diagram"/> <figcaption><code>toList . toHList = id</code> <span class="and">&amp;</span> <code>toHList . toList = id</code> <span style="visibility:hidden"><span class="and">&amp;</span></span><br/> therefore <code>[]</code> <span class="and">&amp;</span> <code>List</code> are <span class="orange">isomorph</span>. </figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2 id="natural-transformation-examples-34">Natural Transformation Examples (3/4)</h2>
<pre><code class="haskell small">toMaybe :: [a] -> Maybe a
toMaybe [] = Nothing
toMaybe (x:xs) = Just x</code></pre>
<p><code>toMaybe</code> is a natural transformation. It is also a morphism from <code>[]</code> to <code>Maybe</code> in the Category of \(\Hask\) endofunctors.</p>
<img style="float:left;width:30%;margin-left:1em;" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/nattrans-list-maybe.png" alt="natural transformation commutative diagram"/>
<figure style="float:right;width:50%">
<img style="width:40%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/list-maybe-endofunctor-morphism.png" alt="natural transformation commutative diagram"/>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2 id="natural-transformation-examples-44">Natural Transformation Examples (4/4)</h2>
<pre><code class="haskell small">mToList :: Maybe a -> [a]
mToList Nothing = []
mToList Just x = [x]</code></pre>
<p><code>toMaybe</code> is a natural transformation. It is also a morphism from <code>[]</code> to <code>Maybe</code> in the Category of \(\Hask\) endofunctors.</p>
<img style="float:left;width:30%;margin-left:1em;" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/nattrans-maybe-list.png" alt="natural transformation commutative diagram"/>
<figure style="float:right;width:50%">
<img style="width:40%" src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/maybe-list-endofunctor-morphsm.png" alt="relation between [] and Maybe"/> <figcaption>There is <span class="red">no isomorphism</span>.<br/> Hint: <code>Bool</code> lists longer than 1. </figcaption>
</figure>
<div class="flush"></div></section>
<section class="slide">
<h2 id="composition-problem">Composition problem</h2>
<p>The Problem; example with lists:</p>
<pre class="haskell"><code>f x = [x] ⇒ f 1 = [1] ⇒ (f.f) 1 = [[1]] ✗
g x = [x+1] ⇒ g 1 = [2] ⇒ (g.g) 1 = ERROR [2]+1 ✗
h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h.h) 1 = ERROR [2,3]+1 ✗ </code></pre>
<p>The same problem with most <code>f :: a -&gt; F a</code> functions and functor <code>F</code>.</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="composition-fixable">Composition Fixable?</h2>
<p>How to fix that? We want to construct an operator which is able to compose:</p>
<p><code>f :: a -&gt; F b</code> <span class="and">&amp;</span> <code>g :: b -&gt; F c</code>.</p>
<p>More specifically we want to create an operator ◎ of type</p>
<p><code>◎ :: (b -&gt; F c) -&gt; (a -&gt; F b) -&gt; (a -&gt; F c)</code></p>
<p>Note: if <code>F</code> = I, ◎ = <code>(.)</code>.</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="fix-composition-12">Fix Composition (1/2)</h2>
<p>Goal, find: <code>◎ :: (b -&gt; F c) -&gt; (a -&gt; F b) -&gt; (a -&gt; F c)</code><br /><code>f :: a -&gt; F b</code>, <code>g :: b -&gt; F c</code>:</p>
<ul>
<li><code>(g ◎ f) x</code> ???</li>
<li>First apply <code>f</code> to <code>x</code> ⇒ <code>f x :: F b</code></li>
<li>Then how to apply <code>g</code> properly to an element of type <code>F b</code>?</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="fix-composition-22">Fix Composition (2/2)</h2>
<p>Goal, find: <code>◎ :: (b -&gt; F c) -&gt; (a -&gt; F b) -&gt; (a -&gt; F c)</code><br /><code>f :: a -&gt; F b</code>, <code>g :: b -&gt; F c</code>, <span class="orange"><code>f x :: F b</code></span>:</p>
<ul>
<li>Use <code>fmap :: (t -&gt; u) -&gt; (F t -&gt; F u)</code>!</li>
<li><code>(fmap g) :: F b -&gt; F (F c)</code> ; (<code>t=b</code>, <code>u=F c</code>)</li>
<li><code>(fmap g) (f x) :: F (F c)</code> it almost WORKS!</li>
<li>We lack an important component, <code>join :: F (F c) -&gt; F c</code></li>
<li><code>(g ◎ f) x = join ((fmap g) (f x))</code> ☺<br />◎ is the Kleisli composition; in Haskell: <code>&lt;=&lt;</code> (in <code>Control.Monad</code>).</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="necessary-laws">Necessary laws</h2>
<p>For ◎ to work like composition, we need join to hold the following properties:</p>
<ul>
<li><code>join (join (F (F (F a))))=join (F (join (F (F a))))</code></li>
<li>abusing notations denoting <code>join</code> by ⊙; this is equivalent to<br /><span class="orange"><code>(F ⊙ F) ⊙ F = F ⊙ (F ⊙ F)</code></span></li>
<li>There exists <code>η :: a -&gt; F a</code> s.t.<br /><span class="orange"><code>η⊙F=F=F⊙η</code></span></li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="klesli-composition">Klesli composition</h2>
<p>Now the composition works as expected. In Haskell ◎ is <code>&lt;=&lt;</code> in <code>Control.Monad</code>.</p>
<p><code>g &lt;=&lt; f = \x -&gt; join ((fmap g) (f x))</code></p>
<pre class="haskell"><code>f x = [x] ⇒ f 1 = [1] ⇒ (f <=< f) 1 = [1] ✓
g x = [x+1] ⇒ g 1 = [2] ⇒ (g <=< g) 1 = [3] ✓
h x = [x+1,x*3] ⇒ h 1 = [2,3] ⇒ (h <=< h) 1 = [3,6,4,9] ✓</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="we-reinvented-monads">We reinvented Monads!</h2>
<p>A monad is a triplet <code>(M,⊙,η)</code> where</p>
<ul>
<li>\(M\) an <span class="orange">Endofunctor</span> (to type <code>a</code> associate <code>M a</code>)</li>
<li>\(⊙:M×M→M\) a <span class="orange">nat. trans.</span> (i.e. <code>⊙::M (M a) → M a</code> ; <code>join</code>)</li>
<li>\(η:I→M\) a <span class="orange">nat. trans.</span> (\(I\) identity functor ; <code>η::a → M a</code>)</li>
</ul>
<p>Satisfying</p>
<ul>
<li>\(M ⊙ (M ⊙ M) = (M ⊙ M) ⊙ M\)</li>
<li>\(η ⊙ M = M = M ⊙ η\)</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="compare-with-monoid">Compare with Monoid</h2>
<p>A Monoid is a triplet \((E,∙,e)\) s.t.</p>
<ul>
<li>\(E\) a set</li>
<li>\(∙:E×E→E\)</li>
<li>\(e:1→E\)</li>
</ul>
<p>Satisfying</p>
<ul>
<li>\(x∙(y∙z) = (x∙y)∙z, ∀x,y,z∈E\)</li>
<li>\(e∙x = x = x∙e, ∀x∈E\)</li>
</ul>
<div class="flush"></div></section>
<section class="slide">
<h2 id="monads-are-just-monoids">Monads are just Monoids</h2>
<blockquote>
<p>A Monad is just a monoid in the category of endofunctors, what's the problem?</p>
</blockquote>
<p>The real sentence was:</p>
<blockquote>
<p>All told, a monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor.</p>
</blockquote>
<div class="flush"></div></section>
<section class="slide">
<h2 id="example-list">Example: List</h2>
<ul>
<li><code>[] :: * -&gt; *</code> an <span class="orange">Endofunctor</span></li>
<li>\(⊙:M×M→M\) a nat. trans. (<code>join :: M (M a) -&gt; M a</code>)</li>
<li>\(η:I→M\) a nat. trans.</li>
</ul>
<pre class="haskell"><code>-- In Haskell ⊙ is "join" in "Control.Monad"
join :: [[a]] -> [a]
join = concat
-- In Haskell the "return" function (unfortunate name)
η :: a -> [a]
η x = [x]</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="example-list-law-verification">Example: List (law verification)</h2>
<p>Example: <code>List</code> is a functor (<code>join</code> is ⊙)</p>
<ul>
<li>\(M ⊙ (M ⊙ M) = (M ⊙ M) ⊙ M\)</li>
<li>\(η ⊙ M = M = M ⊙ η\)</li>
</ul>
<pre class="nohighlight small"><code>join [ join [[x,y,...,z]] ] = join [[x,y,...,z]]
= join (join [[[x,y,...,z]]])
join (η [x]) = [x] = join [η x]</code></pre>
<p>Therefore <code>([],join,η)</code> is a monad.</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="monads-utility">Monads useful?</h2>
<p>A <em>LOT</em> of monad tutorial on the net. Just one example; the State Monad</p>
<p><code>DrawScene</code> to <code><span class="orange">State Screen</span> DrawScene</code> ; still <b>pure</b>.</p>
<pre class="haskell left smaller" style="width:40%"><code>main = drawImage (width,height)
drawImage :: Screen -&gt; DrawScene
drawImage <span class="orange">screen</span> = do
drawPoint p <span class="orange">screen</span>
drawCircle c <span class="orange">screen</span>
drawRectangle r <span class="orange">screen</span>
drawPoint point <span class="orange">screen</span> = ...
drawCircle circle <span class="orange">screen</span> = ...
drawRectangle rectangle <span class="orange">screen</span> = ...</code></pre>
<pre class="haskell right smaller" style="width:40%"><code>main = do
<span class="orange">put (Screen 1024 768)</span>
drawImage
drawImage :: State Screen DrawScene
drawImage = do
drawPoint p
drawCircle c
drawRectangle r
drawPoint :: Point -&gt;
State Screen DrawScene
drawPoint p = do
<span class="orange">Screen width height &lt;- get</span>
...</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="fold"><code>fold</code></h2>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/tower_folded.gif" alt="fold" style="width:50%;max-width:50%"/>
<div class="flush"></div></section>
<section class="slide">
<h2 id="κατα-morphism">κατα-morphism</h2>
<img src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/earth_catamorphed.gif" alt="catamorphism" style="width:90%;max-width:90%"/>
<div class="flush"></div></section>
<section class="slide">
<h2 id="κατα-morphism-fold-generalization">κατα-morphism: fold generalization</h2>
<p><code>acc</code> type of the &quot;accumulator&quot;:<br /><code>fold :: (acc -&gt; a -&gt; acc) -&gt; acc -&gt; [a] -&gt; acc</code></p>
<p>Idea: put the accumulated value inside the type.</p>
<pre class="haskell"><code>-- Equivalent to fold (+1) 0 "cata"
(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' Nil))))
(Cons 'c' (Cons 'a' (Cons 't' (Cons 'a' <span style="border: solid 1px;">0</span>))))
(Cons 'c' (Cons 'a' (Cons 't' <span style="border: solid 1px;">1</span>)))
(Cons 'c' (Cons 'a' <span style="border: solid 1px;">2</span>))
(Cons 'c' <span style="border: solid 1px;">3</span>)
<span style="border: solid 1px;">4</span></code></pre>
<p>But where are all the informations? <code>(+1)</code> and <code>0</code>?</p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="κατα-morphism-missing-information">κατα-morphism: Missing Information</h2>
<p>Where is the missing information?</p>
<ul>
<li>Functor operator <code>fmap</code></li>
<li>Algebra representing the <code>(+1)</code> and also knowing about the <code>0</code>.</li>
</ul>
<p>First example, make <code>length</code> on <code>[Char]</code></p>
<div class="flush"></div></section>
<section class="slide">
<h2 id="κατα-morphism-type-work">κατα-morphism: Type work</h2>
<pre class="haskell"><code>
data StrF a = Cons Char a | Nil
data Str' = StrF Str'
-- generalize the construction of Str to other datatype
-- Mu: type fixed point
-- Mu :: (* -> *) -> *
data Mu f = InF { outF :: f (Mu f) }
data Str = Mu StrF
-- Example
foo=InF { outF = Cons 'f'
(InF { outF = Cons 'o'
(InF { outF = Cons 'o'
(InF { outF = Nil })})})}</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="κατα-morphism-missing-information-retrieved">κατα-morphism: missing information retrieved</h2>
<pre class="haskell"><code>type Algebra f a = f a -> a
instance Functor (StrF a) =
fmap f (Cons c x) = Cons c (f x)
fmap _ Nil = Nil</code></pre>
<pre class="haskell"><code>cata :: Functor f => Algebra f a -> Mu f -> a
cata f = f . fmap (cata f) . outF</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="κατα-morphism-finally-length">κατα-morphism: Finally length</h2>
<p>All needed information for making length.</p>
<pre><code>instance Functor (StrF a) =
fmap f (Cons c x) = Cons c (f x)
fmap _ Nil = Nil
length&#39; :: Str -&gt; Int
length&#39; = cata phi where
phi :: Algebra StrF Int -- StrF Int -&gt; Int
phi (Cons a b) = 1 + b
phi Nil = 0
main = do
l &lt;- length&#39; $ stringToStr &quot;Toto&quot;
...</code></pre>
<div class="flush"></div></section>
<section class="slide">
<h2 id="κατα-morphism-extension-to-trees">κατα-morphism: extension to Trees</h2>
<p>Once you get the trick, it is easy to extent to most Functor.</p>
<pre><code>type Tree = Mu TreeF
data TreeF x = Node Int [x]
instance Functor TreeF where
fmap f (Node e xs) = Node e (fmap f xs)
depth = cata phi where
phi :: Algebra TreeF Int -- TreeF Int -&gt; Int
phi (Node x sons) = 1 + foldr max 0 sons</code></pre>
<div class="flush"></div></section>
<section class="slide last">
<h2 id="conclusion">Conclusion</h2>
<p>Category Theory oriented Programming:</p>
<ul>
<li>Focus on the type and operators</li>
<li>Extreme generalisation</li>
<li>Better modularity</li>
<li>Better control through properties of types</li>
</ul>
<p><span class="smaller">No cat were harmed in the making of this presentation.</span></p>
<div class="flush"></div></section>
]]></summary>
</entry>
</feed>