<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 I’ll help SPJ achieve this honorable goal.</p>
</div>
<h2id="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? Isn’t it only a language for student! I don’t 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 don’t even have classes!!!! Can you imagine? I don’t even speak about class inheritance.</p>
<p>We’re in 2016! And they don’t 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. I’m not fan of their Stop the World GC.</p>
</blockquote>
<p>If they come from LISP and the statically typed language remark wasn’t enough. Try to mention the lack of macros in Haskell. Don’t mention template Haskell or even less Generics and all recent progress in GHC.</p>
<h2id="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>
<h2id="make-it-difficult-to-learn">Make it difficult to learn</h2>
<h3id="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 you’ll 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>
<h3id="tutorial-authors">Tutorial authors</h3>
<p>Please don’t provide an obvious first example like:</p>
<aclass="sourceLine"id="cb2-27"title="27"> setPort port <spanclass="op">$</span></a>
<aclass="sourceLine"id="cb2-28"title="28"> setBeforeMainLoop (hPutStrLn stderr (<spanclass="st">"listening on port "</span><spanclass="op">++</span><spanclass="fu">show</span> port)) <spanclass="op">$</span></a>
<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>:<|></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! You’ll 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. You’ll 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 don’t 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 you’re afraid that this example might be too close to a real world product, you can simply use some advanced lenses examples:</p>
<divclass="sourceCode"id="cb3"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb3-1"title="1"><spanclass="ot">{-# LANGUAGE DeriveGeneric #-}</span></a>
<aclass="sourceLine"id="cb3-2"title="2"><spanclass="ot">{-# LANGUAGE TemplateHaskell #-}</span></a>
<aclass="sourceLine"id="cb3-8"title="8"><spanclass="kw">data</span><spanclass="dt">Example</span> a b c <spanclass="ot">=</span><spanclass="dt">C1</span> a <spanclass="op">|</span><spanclass="dt">C2</span> b <spanclass="op">|</span><spanclass="dt">C3</span> c <spanclass="kw">deriving</span> (<spanclass="dt">Generic</span>)</a>
<aclass="sourceLine"id="cb3-12"title="12"><spanclass="kw">instance</span> (<spanclass="dt">Empty</span> a, <spanclass="dt">Empty</span> b, <spanclass="dt">Empty</span> c) <spanclass="ot">=></span><spanclass="dt">Empty</span> (<spanclass="dt">Example</span> a b c)</a>
<aclass="sourceLine"id="cb3-16"title="16"><spanclass="op">&</span> on _C1 (\s <spanclass="ot">-></span> s )</a>
<aclass="sourceLine"id="cb3-17"title="17"><spanclass="op">&</span> on _C2 (\c <spanclass="ot">-></span><spanclass="fu">replicate</span><spanclass="dv">3</span> c )</a>
<aclass="sourceLine"id="cb3-18"title="18"><spanclass="op">&</span> on _C3 (\n <spanclass="ot">-></span><spanclass="fu">replicate</span> n <spanclass="ch">'!'</span>)</a></code></pre></div>
<p>Certainly a great example to start a new language with.</p>
<h3id="library-authors">Library authors</h3>
<oltype="1">
<li>Do your best not to respect versioning number policy to maximize the probability to break things.</li>
<li>Don’t 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 -> String -> IO ()</code> by <code>(<=.=$$.)</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>
<h2id="conclusion-mistake">Conclusion & 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 didn’t asked to <code>avoid success $ at all cost</code> but to <code>avoid $ success at all cost</code><ahref="#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>I’m 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>
<sectionclass="footnotes">
<hr/>
<ol>
<liid="fn1"><p>A good point to use more LISP syntax.<ahref="#fnref1"class="footnote-back">↩</a></p></li>
<p><spanclass="sc"><abbrtitle="Too long; didn't read">tl;dr</abbr>: </span> Some hints on how to make great documentation for Haskell libraries.</p>
<oltype="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 wasn’t 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>
<oltype="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>
<h2id="hints">Hints</h2>
<h3id="tutorialsguides">Tutorials/Guides</h3>
<oltype="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>
<p>To prevent obsolescence of your tutorial, use <code>doctest</code>.</p>
<p>That way when you’ll do a <code>stack test</code> or <code>cabal test</code> you’ll get errors if some example doesn’t work anymore.</p>
<h3id="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>
<divclass="sourceCode"id="cb2"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb2-1"title="1"><spanclass="co">-- | My function description</span></a>
<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 <ahref="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 <ahref="http://docs.haskellstack.org/en/stable/GUIDE/#travis-with-caching">here</a> and remove the builds you don’t 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>
<p>If you didn’t declared your package to <code>stackage</code>, please do it. It isn’t much work. Just edit a file to add your package. And you’ll could be able to add another badge:</p>
<divclass="sourceCode"id="cb9"><preclass="sourceCode .markdown"><codeclass="sourceCode markdown"><aclass="sourceLine"id="cb9-1"title="1"><spanclass="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 <ahref="https://www.fpcomplete.com/blog/2015/10/stackage-badges">Stackage Badges</a> for more informations.</p>
<h3id="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: 'Copyright: (c) 2016 Your Name'
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>
= C { a :: TypeA <spanclass="highlight">-- ^ field a description</span>
, b :: TypeB <spanclass="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 -> 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>
<h2id="other-random-ideas">Other Random Ideas</h2>
<p>In Haskell we have great tools like <ahref="http://hayoo.fh-wedel.de"><code>hayoo!</code></a> and <ahref="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>
<h3id="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><ahref="https://jacobian.org/writing/what-to-write/">What to write</a></li>
</ul>
<h3id="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><ahref="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 don’t only have the details and standard documentation. You’ll 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><ahref="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 <ahref="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>
<oltype="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>
<h2id="design-is-important"><strong>Design is important</strong></h2>
<div>
<imgsrc="/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 wouldn’t like to replace all long and precise documentation with short human unprecise concepts. I don’t 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>
<p><spanclass="sc"><abbrtitle="Trop long; pas lu">tlpl</abbr>: </span> Comment utiliser vim comme une IDE très efficace</p>
<p>In <ahref="/Scratch/en/blog/Learn-Vim-Progressively/">Learn Vim Progressively</a> I’ve show how Vim is great for editing text, and navigating in the same file (buffer). In this short article you’ll see how I use Vim as an IDE. Mainly by using some great plugins.</p>
<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. I’ll separate each part by <code>...</code> in the code.</p>
<p>Before anything, you should protect your eyes using a readable and low contrast colorscheme.</p>
<p>For this I use <ahref="http://ethanschoonover.com/solarized">solarized dark</a>. To add it, you only have to write this in your <code>~/.vimrc</code> file:</p>
<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 <ahref="https://github.com/ggreer/the_silver_searcher"><code>ag</code> (the silver search)</a>. If you don’t 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>
<preclass="vim"><code>" Unite
" depend on vimproc
" ------------- VERY IMPORTANT ------------
" you have to go to .vim/plugin/vimproc.vim and do a ./make
" -----------------------------------------
Plug 'Shougo/vimproc.vim'
Plug 'Shougo/unite.vim'
...
let g:unite_source_history_yank_enable = 1
try
let g:unite_source_rec_async_command='ag --nocolor --nogroup -g ""'
<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>
<p>Don’t 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><space>/</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>
<h3id="basic-auto-completion-c-n-c-p">Basic auto completion: <code>C-n</code>&<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>
<h2id="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>☞ Don’t forget to install <code>ghc-mod</code> with: <code>cabal install ghc-mod</code></p>
</blockquote>
<preclass="vim"><code>" ---------- VERY IMPORTANT -----------
<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 I’ll be able to make a useful vim plugin.</p>
<p>So mainly you’ll 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>
<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>
<h2id="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>
<imgsrc="/Scratch/img/blog/Safer-Haskell-Install/main.jpg"alt="to Haskell and Beyond!!!"/>
</div>
<divclass="intro">
<p><spanclass="sc"><abbrtitle="Trop long; pas lu">tlpl</abbr>: </span> Pour installer Haskell (OS X et Linux) copiez/collez les lignes suivante dans un terminal :</p>
<p>Si vous êtes sous windows, téléchargez Haskell Platform et suivez les instructions pour utiliser <ahref="http://www.stackage.org/lts">Haskell LTS</a>.</p>
<p>Si vous voulez savoir le pourquoi et le comment ; lisez le reste de l’article.</p>
</div>
<h2id="pourquoi">Pourquoi ?</h2>
<p>La plus grande faiblesse d’Haskell n’a rien à voir avec le langage en lui-même mais avec son écosystème.</p>
<p>The main problem I’ll 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 <ahref="http://www.stackage.org">stackage</a>.</p>
<p>So to install copy/paste the following three lines in your terminal:</p>
<p>You can read the script and you will see that this is quite straightforward.</p>
<oltype="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 <ahref="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 <ahref="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>
<h2id="some-last-words">Some Last Words</h2>
<p>This script use the latest <ahref="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 didn’t 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> didn’t 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, <ahref="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<ahref="#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 <ahref="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 won’t work anymore in stackage. And whether the developer fix its package or all other packages upgrade their usage. During this time, <ahref="http://www.stackage.org/lts">Haskell LTS</a> end-users will be able to develop without dependency issues.</p>
<hr/>
<pclass="small">
<ahref="https://www.flickr.com/photos/nesster/4198442186/">The image of the cat about to jump that I slightly edited can found here</a>
</p>
<sectionclass="footnotes">
<hr/>
<ol>
<liid="fn1"><p>I myself am guilty of such behavior. It was a beginner error.<ahref="#fnref1"class="footnote-back">↩</a></p></li>
<p><spanclass="sc"><abbrtitle="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 && cabal install holy-project</code>.</p>
</div>
<p>I recently read this excellent article: <ahref="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<ahref="#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>
<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>
<h3id="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
<spanclass="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>
<spanclass="yellow">You: Ask me the questions, bridgekeeper, I am not afraid.</span>
<spanclass="green">Bridgekeeper: What is the name of your project?</span>
> Holy project
<spanclass="green">Bridgekeeper: What is your name?</span> (Yann Esposito (Yogsototh))
>
<spanclass="green">Bridgekeeper: What is your email?</span> (Yann.Esposito@gmail.com)
>
<spanclass="green">Bridgekeeper: What is your github user name?</span> (yogsototh)
>
<spanclass="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: <spanclass="green">OK</span>
coconut
coconut: <spanclass="green">OK</span>
coconut property: <spanclass="green">OK</span>
148 tests completed
<spanclass="green">All 3 tests passed</span>
<spanclass="green">Bridgekeeper: What... is the air-speed velocity of an unladen swallow?</span>
<spanclass="yellow">You: What do you mean? An African or European swallow?</span>
<spanclass="green">Bridgekeeper: Huh? I... I don't know that.</span>
Sir Bedevere: How do you know so much about swallows?
<spanclass="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>
<h3id="the-dialogs">The dialogs</h3>
<div>
<imgsrc="/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>
<aclass="sourceLine"id="cb3-4"title="4"><spanclass="kw">for</span><spanclass="ex">COLOR</span> in RED GREEN YELLOW BLUE MAGENTA CYAN BLACK WHITE<spanclass="kw">;</span><spanclass="kw">do</span></a>
<aclass="sourceLine"id="cb3-16"title="16"><spanclass="ex">bk</span><spanclass="st">"Who would cross the Bridge of Death"</span></a>
<aclass="sourceLine"id="cb3-17"title="17"><spanclass="ex">bk</span><spanclass="st">"must answer me these questions three,"</span></a>
<aclass="sourceLine"id="cb3-18"title="18"><spanclass="ex">bk</span><spanclass="st">"ere the other side he see."</span></a>
<aclass="sourceLine"id="cb3-19"title="19"><spanclass="ex">you</span><spanclass="st">"Ask me the questions, bridgekeeper, I am not afraid.\n"</span></a>
<aclass="sourceLine"id="cb3-23"title="23"><spanclass="ex">bk</span><spanclass="st">"What... is the air-speed velocity of an unladen swallow?"</span></a>
<aclass="sourceLine"id="cb3-24"title="24"><spanclass="ex">you</span><spanclass="st">"What do you mean? An African or European swallow?"</span></a>
<aclass="sourceLine"id="cb3-25"title="25"><spanclass="ex">bk</span><spanclass="st">"Huh? I... I don't know that."</span></a>
<aclass="sourceLine"id="cb3-26"title="26"><spanclass="ex">log</span><spanclass="st">"[the bridgekeeper is thrown over]"</span></a>
<aclass="sourceLine"id="cb3-28"title="28"><spanclass="ex">log</span><spanclass="st">"Sir Bedevere: How do you know so much about swallows?"</span></a>
<aclass="sourceLine"id="cb3-29"title="29"><spanclass="ex">you</span><spanclass="st">"Well, you have to know these things when you're a king, you know."</span></a></code></pre></div>
<p>In the first Haskell version I don’t use colors. We see we can almost copy/paste. I just added the types.</p>
<aclass="sourceLine"id="cb4-21"title="21"> bk <spanclass="st">"What... is the air-speed velocity of an unladen swallow?"</span></a>
<aclass="sourceLine"id="cb4-22"title="22"> you <spanclass="st">"What do you mean? An African or European swallow?"</span></a>
<aclass="sourceLine"id="cb4-23"title="23"> bk <spanclass="st">"Huh? I... I don't know that."</span></a>
<aclass="sourceLine"id="cb4-24"title="24"><spanclass="fu">putStrLn</span><spanclass="st">"[the bridgekeeper is thrown over]"</span></a>
<aclass="sourceLine"id="cb4-25"title="25"> bk <spanclass="st">"Auuuuuuuuuuuugh"</span></a>
<aclass="sourceLine"id="cb4-26"title="26"><spanclass="fu">putStrLn</span><spanclass="st">"Sir Bedevere: How do you know so much about swallows?"</span></a>
<aclass="sourceLine"id="cb4-27"title="27"> you <spanclass="st">"Well, you have to know these things when you're a king, you know."</span></a></code></pre></div>
<p>Now let’s just add the colors using the <ahref="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>
<aclass="sourceLine"id="cb6-30"title="30"> bk <spanclass="st">"What... is the air-speed velocity of an unladen swallow?"</span></a>
<aclass="sourceLine"id="cb6-31"title="31"> you <spanclass="st">"What do you mean? An African or European swallow?"</span></a>
<aclass="sourceLine"id="cb6-32"title="32"> bk <spanclass="st">"Huh? I... I don't know that."</span></a>
<aclass="sourceLine"id="cb6-33"title="33"><spanclass="fu">putStrLn</span><spanclass="st">"[the bridgekeeper is thrown over]"</span></a>
<aclass="sourceLine"id="cb6-34"title="34"> bk <spanclass="st">"Auuuuuuuuuuuugh"</span></a>
<aclass="sourceLine"id="cb6-35"title="35"><spanclass="fu">putStrLn</span><spanclass="st">"Sir Bedevere: How do you know so much about swallows?"</span></a>
<aclass="sourceLine"id="cb6-36"title="36"> you <spanclass="st">"Well, you have to know these things when you're a king, you know."</span></a></code></pre></div>
<p>We could put this code in <code>src/Main.hs</code>. Declare a main function:</p>
<p>Make <code>cabal install</code> and run <code>cabal run</code> (or <code>./.cabal-sandbox/bin/holy-project</code>). It works!</p>
<h2id="five-questions-three-questions-sir">Five Questions – Three questions Sir!</h2>
<div>
<imgsrc="/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>
<divclass="sourceCode"id="cb8"><preclass="sourceCode bash"><codeclass="sourceCode bash"><aclass="sourceLine"id="cb8-1"title="1"><spanclass="ex">print</span> -- <spanclass="st">"What is your name?"</span></a>
<p>If we want to abstract things a bit, the easiest way in shell is to use a global variable<ahref="#fn2"class="footnote-ref"id="fnref2"><sup>2</sup></a> which will get the value of the user input like this:</p>
<aclass="sourceLine"id="cb9-4"title="4"><spanclass="ex">bk</span><spanclass="st">"What is your </span><spanclass="va">$info</span><spanclass="st">?"</span></a>
<aclass="sourceLine"id="cb10-4"title="4">ask info <spanclass="ot">=</span><spanclass="kw">do</span></a>
<aclass="sourceLine"id="cb10-5"title="5"> bk <spanclass="op">$</span><spanclass="st">"What is your "</span><spanclass="op">++</span> info <spanclass="op">++</span><spanclass="st">"?"</span></a>
<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>
<h2id="using-answers">Using answers</h2>
<div>
<imgsrc="/Scratch/img/blog/Holy-Haskell-Starter/castle-of-hhhhaaaarr.jpg"alt="Castle of Aaaaarrrr????"/>
</div>
<h3id="create-the-project-name">Create the project name</h3>
<p>I don’t really like the ability to use capital letter in a package name. So in shell I transform the project name like this:</p>
<divclass="sourceCode"id="cb12"><preclass="sourceCode bash"><codeclass="sourceCode bash"><aclass="sourceLine"id="cb12-1"title="1"><spanclass="co"># replace all spaces by dashes then lowercase the string</span></a>
<divclass="sourceCode"id="cb16"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb16-1"title="1"><spanclass="co">-- | transform a chain like "Holy project" in "HolyProject"</span></a>
<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:
"Holy-grail" ==( sed 's/-/ /g' )=>"Holy<spanclass="highlight"></span>grail"
<p>Which verify the project name is not empty and use only letter, numbers and dashes:</p>
<divclass="sourceCode"id="cb19"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb19-1"title="1"><spanclass="co">-- | verify if project name is conform</span></a>
<p>In Haskell, while possible, we shouldn’t 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 <ahref="http://hackage.haskell.org/package/hastache"><code>hastache</code></a>, a Haskell implementation of Mustache templates<ahref="#fn3"class="footnote-ref"id="fnref3"><sup>3</sup></a>.</p>
<h3id="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>
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>
<h3id="create-files-and-directories">Create files and directories</h3>
<p>A first remark is for portability purpose we shouldn’t use String for file path. For example on Windows <code>/</code> isn’t considered as a subdirectory character. To resolve this problem we will use <code>FilePath</code>:</p>
<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>
<divclass="sourceCode"id="cb25"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb25-1"title="1"><spanclass="ot">{-# LANGUAGE DeriveDataTypeable #-}</span></a>
<aclass="sourceLine"id="cb27-12"title="12"><spanclass="highlight">in_synopsis</span><spanclass="ot"><-</span> ask <spanclass="st">"project in less than a dozen word?"</span></a>
<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>
<aclass="sourceLine"id="cb30-9"title="9"> bk <spanclass="st">"What... is your favourite colour?"</span></a>
<aclass="sourceLine"id="cb30-10"title="10"> you <spanclass="st">"Blue. No, yel..."</span></a>
<aclass="sourceLine"id="cb30-11"title="11"><spanclass="fu">putStrLn</span><spanclass="st">"[You are thrown over the edge into the volcano]"</span></a>
<aclass="sourceLine"id="cb30-12"title="12"> you <spanclass="st">"You: Auuuuuuuuuuuugh"</span></a>
<aclass="sourceLine"id="cb30-13"title="13"> bk <spanclass="st">" Hee hee heh."</span></a>
<aclass="sourceLine"id="cb30-16"title="16"> bk <spanclass="st">"What is the capital of Assyria?"</span></a>
<aclass="sourceLine"id="cb30-17"title="17"> you <spanclass="st">"I don't know that!"</span></a>
<aclass="sourceLine"id="cb30-18"title="18"><spanclass="fu">putStrLn</span><spanclass="st">"[You are thrown over the edge into the volcano]"</span></a>
<aclass="sourceLine"id="cb30-19"title="19"> you <spanclass="st">"Auuuuuuuuuuuugh"</span></a>
<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, let’s take advantage of this library.</p>
<aclass="sourceLine"id="cb33-2"title="2">ask info hint <spanclass="ot">=</span><spanclass="kw">do</span></a>
<aclass="sourceLine"id="cb33-3"title="3"> bk <spanclass="op">$</span><spanclass="st">"What is your "</span><spanclass="op">++</span> info <spanclass="op">++</span><spanclass="st">"?"</span><spanclass="op">++</span><spanclass="highlight">(<spanclass="fu">maybe</span><spanclass="st">""</span> (\h <spanclass="ot">-></span><spanclass="st">" ("</span><spanclass="op">++</span>h<spanclass="op">++</span><spanclass="st">")"</span>) hint)</span></a>
<aclass="sourceLine"id="cb34-14"title="14"><spanclass="co">-- return the first Just value of a list of Maybe</span></a>
<aclass="sourceLine"id="cb34-15"title="15"><spanclass="ot">firstJust ::</span> (<spanclass="dt">Eq</span> a) <spanclass="ot">=></span> [<spanclass="dt">Maybe</span> a] <spanclass="ot">-></span><spanclass="dt">Maybe</span> a</a>
<aclass="sourceLine"id="cb34-16"title="16">firstJust l <spanclass="ot">=</span><spanclass="kw">case</span><spanclass="fu">dropWhile</span> (<spanclass="op">==</span><spanclass="dt">Nothing</span>) l <spanclass="kw">of</span></a>
<aclass="sourceLine"id="cb34-24"title="24"><spanclass="ot">-></span> [<spanclass="dt">LZ.ByteString</span>] <spanclass="co">-- line of words</span></a>
<aclass="sourceLine"id="cb34-25"title="25"><spanclass="ot">-></span><spanclass="dt">Maybe</span><spanclass="dt">String</span><spanclass="co">-- the value if found</span></a>
<aclass="sourceLine"id="cb34-26"title="26">getValueForKey el (n<spanclass="op">:</span>e<spanclass="op">:</span>xs) <spanclass="ot">=</span><spanclass="kw">if</span> (n <spanclass="op">==</span> (LZ.pack el)) <spanclass="op">&&</span> (e <spanclass="op">==</span> (LZ.pack <spanclass="st">"="</span>))</a>
<p>We could notice, <code>getNameAndMail</code> doesn’t read the full file and stop at the first occurrence of name and mail.</p>
<h3id="use-the-github-api">Use the github API</h3>
<div>
<imgsrc="/Scratch/img/blog/Holy-Haskell-Starter/coconut.jpg"alt="Coconut and Swallow"/>
</div>
<p>The task seems relatively easy, but we’ll see there will be some complexity hidden. Make a request on <code>https://api.github.com/search/users?q=<email></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>
<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>
<divclass="sourceCode"id="cb36"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb36-1"title="1"><spanclass="ot">{-# LANGUAGE OverloadedStrings #-}</span></a>
<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>
<p>It looks ugly, but it’s 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 <ahref="https://www.fpcomplete.com/user/tel/lens-aeson-traversals-prisms">this article on <code>lens-aeson</code> and prisms</a> to know more.</p>
<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>
<p>While it might feel a bit confusing, it is in fact quite simple.</p>
<oltype="1">
<li>declare an <ahref="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 didn’t 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>
<h2id="project-structure">Project Structure</h2>
<p>We have a working product. But, I don’t 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>
<h3id="modularizing">Modularizing</h3>
<div>
<imgsrc="/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>
<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>
<p>We didn’t 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>
<p>Be sure to have <code>haddock</code> in your <code>PATH</code>. You could for example add it like this:</p>
<divclass="sourceCode"id="cb41"><preclass="sourceCode bash"><codeclass="sourceCode bash"><aclass="sourceLine"id="cb41-1"title="1"><spanclass="co"># You might want to add this line in your .profile</span></a>
<p>And magically, you’ll have a documentation in <code>dist/doc/html/holy-project/index.html</code>.</p>
<h3id="tests">Tests</h3>
<p>While the Haskell static typing is quite efficient to prevent entire classes of bugs, Haskell doesn’t discard the need to test to minimize the number of bugs.</p>
<h4id="unit-testing-with-hunit">Unit Testing with HUnit</h4>
<div>
<imgsrc="/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>
<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>. Let’s create a file <code>test/HolyProject/GithubAPI/Test.hs</code> with the following content:</p>
<aclass="sourceLine"id="cb44-18"title="18"><spanclass="co">-- | Test if some IO action returns some expected value</span></a>
<aclass="sourceLine"id="cb44-19"title="19"><spanclass="ot">ioTestEq ::</span> (<spanclass="dt">Eq</span> a, <spanclass="dt">Show</span> a) <spanclass="ot">=></span><spanclass="dt">IO</span> a <spanclass="ot">-></span> a <spanclass="ot">-></span><spanclass="dt">Assertion</span></a>
<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>
<h4id="property-testing-with-smallcheck-and-quickcheck">Property Testing with SmallCheck and QuickCheck</h4>
<div>
<imgsrc="/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 don’t 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>
<aclass="sourceLine"id="cb45-21"title="21">idempotent f <spanclass="ot">=</span> \s <spanclass="ot">-></span> f s <spanclass="op">==</span> f (f s)</a>
<aclass="sourceLine"id="cb45-22"title="22"></a>
<aclass="sourceLine"id="cb45-23"title="23"><spanclass="ot">deeperIdempotent ::</span> (<spanclass="dt">Eq</span> a, <spanclass="dt">Show</span> a, <spanclass="dt">Serial</span> m a) <spanclass="ot">=></span> (a <spanclass="ot">-></span> a) <spanclass="ot">-></span><spanclass="dt">SC.Property</span> m</a>
<aclass="sourceLine"id="cb45-24"title="24">deeperIdempotent f <spanclass="ot">=</span> forAll <spanclass="op">$</span> SC.changeDepth1 (<spanclass="op">+</span><spanclass="dv">1</span>) <spanclass="op">$</span> \s <spanclass="ot">-></span> f s <spanclass="op">==</span> f (f s)</a></code></pre></div>
*** Failed! Falsifiable (after 19 tests and 5 shrinks):
"a a"
Use --quickcheck-replay '18 913813783 2147483380' to reproduce.
GithubAPI
Yann: <spanclass="green">OK</span>
Jasper: <spanclass="green">OK</span>
<spanclass="red">1 out of 5 tests failed</span>
</pre>
<p>The test fail, but this is not an error. Our <code>capitalize</code> function shouldn’t 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>
<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 didn’t found any counter example. I don’t know how it generates Strings and using deeper search is really long.</p>
<p>Now you could start programming in Haskell and publish your own cabal package.</p>
<sectionclass="footnotes">
<hr/>
<ol>
<liid="fn1"><p>For example, you have to install the test libraries manually to use <code>cabal test</code>.<ahref="#fnref1"class="footnote-back">↩</a></p></li>
<liid="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 doesn’t get access to the standard input<ahref="#fnref2"class="footnote-back">↩</a></p></li>
<liid="fn3"><p>Having a good level of power in templates is very difficult. <spanclass="sc"><abbrtitle="In my Humble Opinion">imho</abbr></span> Mustache has made the best compromise.<ahref="#fnref3"class="footnote-back">↩</a></p></li>
<preclass="sourceCode haskell"><codeclass="sourceCode haskell">f x <spanclass="co">-- ⇔ f(x) in C-like languages</span>
f x y <spanclass="co">-- ⇔ f(x,y)</span></code></pre>
</section>
<sectionclass="slide">
<h2id="haskell-remarks-2">
Haskell Remarks (2)
</h2>
<p>
Don’t mind strange operators (<code><*></code>, <code><$></code>).<br/>Consider them like separators, typically commas.<br/>They are just here to deal with types.
</p>
<p>
Informally:
</p>
<preclass="sourceCode haskell"><codeclass="sourceCode haskell">toto <spanclass="fu"><$></span> x <spanclass="fu"><*></span> y <spanclass="fu"><*></span> z
<spanclass="co">-- ⇔ toto x y z</span>
<spanclass="co">-- ⇔ toto(x,y,z) in C-like languages</span></code></pre>
</section>
<sectionclass="slide">
<h2id="minimal-parsec-examples">
Minimal Parsec Examples
</h2>
<preclass="sourceCode haskell"><codeclass="sourceCode haskell">whitespaces <spanclass="fu">=</span> many (oneOf <spanclass="st">"\t "</span>)
number <spanclass="fu">=</span> many1 digit
symbol <spanclass="fu">=</span> oneOf <spanclass="st">"!#$%<spanclass="and">&</span>|*+-/:<=>?@^_~"</span></code></pre>
<preclass="sourceCode haskell">
<codeclass="sourceCode haskell"><spanclass="st">" \t "</span><spanclass="co">– whitespaces on " \t "</span><spanclass="st">""</span><spanclass="co">– whitespaces on “32”</span><spanclass="st">“32”</span><spanclass="co">– number on “32”</span></li>
<p><spanclass="sc"><abbrtitle="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. <ahref="#the-result">Cliquez ici pour aller au résultats</a>. Cet article n’est disponible qu’en anglais.</p>
</div>
<p>This is it.<br/>
You’ve 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>
<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 didn’t made a bad choice, yes. But …<br/>
you hadn’t 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>
<oltype="1">
<li>Model how to make choice
<oltype="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><ahref="#the-result">Decision tool</a>.</p>
</blockquote>
<h2id="model">Model</h2>
<p>Here are the important features (properties/parameters) I selected to make the choice:</p>
<oltype="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 you’ll 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>
<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>
<h3id="popularity">Popularity</h3>
<p><ahref="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>
<imgsrc="/Scratch/img/blog/Rational-Web-Framework-Choice/mainstreamlanguages.png"alt="Mainstream Languages Cluster from [RedMonk][redmonk]"/>
<figcaption>
Mainstream Languages Cluster from <ahref="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>
<imgsrc="/Scratch/img/blog/Rational-Web-Framework-Choice/secondtierlanguages.png"alt="Second tier languages from [RedMonk][redmonk]"/>
<figcaption>
Second tier languages from <ahref="http://redmonk.com/sogrady/2013/02/28/language-rankings-1-13/">RedMonk</a>
</figcaption>
</figure>
<p>I don’t get into detail, but you could also see third and fourth tier popular languages.</p>
<p><strong>Bad</strong>: third tier <strong>Very Bad</strong>: fourth tier</p>
<p>I don’t 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>
<trclass="header">
<thstyle="text-align: left;">Cluster</th>
<thstyle="text-align: left;">Language</th>
<thstyle="text-align: left;">Framework</th>
<thstyle="text-align: right;">#nb</th>
<thstyle="text-align: right;">%</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<tdstyle="text-align: left;">Excellent</td>
<tdstyle="text-align: left;">Ruby</td>
<tdstyle="text-align: left;">Rails</td>
<tdstyle="text-align: right;">176208</td>
<tdstyle="text-align: right;">100%</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Very Good</td>
<tdstyle="text-align: left;">Python</td>
<tdstyle="text-align: left;">Django</td>
<tdstyle="text-align: right;">57385</td>
<tdstyle="text-align: right;"><50%</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Servlet</td>
<tdstyle="text-align: right;">54139</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Spring</td>
<tdstyle="text-align: right;">31641</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Node.js</td>
<tdstyle="text-align: left;">node.js</td>
<tdstyle="text-align: right;">27243</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Codeigniter</td>
<tdstyle="text-align: right;">21503</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Groovy</td>
<tdstyle="text-align: left;">Grails</td>
<tdstyle="text-align: right;">20222</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Good</td>
<tdstyle="text-align: left;">Ruby</td>
<tdstyle="text-align: left;">Sinatra</td>
<tdstyle="text-align: right;">8631</td>
<tdstyle="text-align: right;"><25%</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Python</td>
<tdstyle="text-align: left;">Flask</td>
<tdstyle="text-align: right;">7062</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Laravel</td>
<tdstyle="text-align: right;">6982</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Kohana</td>
<tdstyle="text-align: right;">5959</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Node.js</td>
<tdstyle="text-align: left;">Express</td>
<tdstyle="text-align: right;">5009</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;">Medium</td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Cake</td>
<tdstyle="text-align: right;">4554</td>
<tdstyle="text-align: right;"><13%</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C♯</td>
<tdstyle="text-align: left;">ServiceStack</td>
<tdstyle="text-align: right;">3838</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Scala</td>
<tdstyle="text-align: left;">Play</td>
<tdstyle="text-align: right;">3823</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Wicket</td>
<tdstyle="text-align: right;">3819</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Dart</td>
<tdstyle="text-align: left;">Dart</td>
<tdstyle="text-align: right;">3753</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Slim</td>
<tdstyle="text-align: right;">3361</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Python</td>
<tdstyle="text-align: left;">Tornado</td>
<tdstyle="text-align: right;">3321</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Scala</td>
<tdstyle="text-align: left;">Lift</td>
<tdstyle="text-align: right;">2844</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: right;">2689</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Bad</td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Tapestry</td>
<tdstyle="text-align: right;">1197</td>
<tdstyle="text-align: right;"><6%</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C♯</td>
<tdstyle="text-align: left;">aspnet</td>
<tdstyle="text-align: right;">1000</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Haskell</td>
<tdstyle="text-align: left;">Yesod</td>
<tdstyle="text-align: right;">889</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Silex</td>
<tdstyle="text-align: right;">750</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Lithium</td>
<tdstyle="text-align: right;">732</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C♯</td>
<tdstyle="text-align: left;">nancy</td>
<tdstyle="text-align: right;">705</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Very bad</td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Grizzly</td>
<tdstyle="text-align: right;">622</td>
<tdstyle="text-align: right;"><3%</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Erlang</td>
<tdstyle="text-align: left;">Cowboy</td>
<tdstyle="text-align: right;">568</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Perl</td>
<tdstyle="text-align: left;">Dancer</td>
<tdstyle="text-align: right;">496</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Symphony2</td>
<tdstyle="text-align: right;">491</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">Revel</td>
<tdstyle="text-align: right;">459</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clojure</td>
<tdstyle="text-align: left;">Compojure</td>
<tdstyle="text-align: right;">391</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Perl</td>
<tdstyle="text-align: left;">Mojolicious</td>
<tdstyle="text-align: right;">376</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Scala</td>
<tdstyle="text-align: left;">Scalatra</td>
<tdstyle="text-align: right;">349</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Scala</td>
<tdstyle="text-align: left;">Finagle</td>
<tdstyle="text-align: right;">336</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Phalcon</td>
<tdstyle="text-align: right;">299</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">js</td>
<tdstyle="text-align: left;">Ringo</td>
<tdstyle="text-align: right;">299</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Gemini</td>
<tdstyle="text-align: right;">276</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Haskell</td>
<tdstyle="text-align: left;">Snap</td>
<tdstyle="text-align: right;">263</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Perl</td>
<tdstyle="text-align: left;">Plack</td>
<tdstyle="text-align: right;">257</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Erlang</td>
<tdstyle="text-align: left;">Elli</td>
<tdstyle="text-align: right;">230</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Dropwizard</td>
<tdstyle="text-align: right;">188</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Yaf</td>
<tdstyle="text-align: right;">146</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Play1</td>
<tdstyle="text-align: right;">133</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Node.js</td>
<tdstyle="text-align: left;">Hapi</td>
<tdstyle="text-align: right;">131</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Java</td>
<tdstyle="text-align: left;">Vertx</td>
<tdstyle="text-align: right;">60</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Scala</td>
<tdstyle="text-align: left;">Unfiltered</td>
<tdstyle="text-align: right;">42</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C</td>
<tdstyle="text-align: left;">onion</td>
<tdstyle="text-align: right;">18</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clojure</td>
<tdstyle="text-align: left;">http-kit</td>
<tdstyle="text-align: right;">17</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Perl</td>
<tdstyle="text-align: left;">Kelp</td>
<tdstyle="text-align: right;">16</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Micromvc</td>
<tdstyle="text-align: right;">13</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Lua</td>
<tdstyle="text-align: left;">Openresty</td>
<tdstyle="text-align: right;">8</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C++</td>
<tdstyle="text-align: left;">cpoll-cppsp</td>
<tdstyle="text-align: right;">5</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clojure</td>
<tdstyle="text-align: left;">Luminus</td>
<tdstyle="text-align: right;">3</td>
<tdstyle="text-align: right;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">Phreeze</td>
<tdstyle="text-align: right;">1</td>
<tdstyle="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 didn’t found a nice way to merge the results from RedMonk with these one. So I’ll use these unperfect one. Hopefully the order of magninute is mostly correct for most framework.</p>
<h3id="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 <ahref="http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=all&data=u64q">benchmarksgame</a>. Mainly, there are five clusters:</p>
<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>These benchmark doesn’t 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>
<trclass="header">
<thstyle="text-align: left;">Cluster</th>
<thstyle="text-align: left;">Language</th>
<thstyle="text-align: left;">Framework</th>
<thstyle="text-align: center;">#nb</th>
<thstyle="text-align: left;">slowness</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<tdstyle="text-align: left;">Excellent</td>
<tdstyle="text-align: left;">C++</td>
<tdstyle="text-align: left;">cpoll-cppsp</td>
<tdstyle="text-align: center;">114,711</td>
<tdstyle="text-align: left;">1×</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">gemini</td>
<tdstyle="text-align: center;">105,204</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Lua</td>
<tdstyle="text-align: left;">openresty</td>
<tdstyle="text-align: center;">93,882</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">servlet</td>
<tdstyle="text-align: center;">90,580</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C++</td>
<tdstyle="text-align: left;">cpoll-pool</td>
<tdstyle="text-align: center;">89,167</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">go</td>
<tdstyle="text-align: center;">76,024</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">finagle</td>
<tdstyle="text-align: center;">68,413</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">revel</td>
<tdstyle="text-align: center;">66,990</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">rest-express</td>
<tdstyle="text-align: center;">63,209</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Very Good</td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">wicket</td>
<tdstyle="text-align: center;">48,772</td>
<tdstyle="text-align: left;">>2×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">scalatra</td>
<tdstyle="text-align: center;">48,594</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">http-kit</td>
<tdstyle="text-align: center;">42,703</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">spring</td>
<tdstyle="text-align: center;">36,643</td>
<tdstyle="text-align: left;">>3×</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">php</td>
<tdstyle="text-align: center;">36,605</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">tapestry</td>
<tdstyle="text-align: center;">35,032</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">compojure</td>
<tdstyle="text-align: center;">32,088</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">ringo</td>
<tdstyle="text-align: center;">31,962</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">dropwizard</td>
<tdstyle="text-align: center;">31,514</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">luminus</td>
<tdstyle="text-align: center;">30,672</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Good</td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">play-slick</td>
<tdstyle="text-align: center;">29,950</td>
<tdstyle="text-align: left;">>4×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">unfiltered</td>
<tdstyle="text-align: center;">29,782</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Erl</td>
<tdstyle="text-align: left;">elli</td>
<tdstyle="text-align: center;">28,862</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">vertx</td>
<tdstyle="text-align: center;">28,075</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">nodejs</td>
<tdstyle="text-align: center;">27,598</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Erl</td>
<tdstyle="text-align: left;">cowboy</td>
<tdstyle="text-align: center;">24,669</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C</td>
<tdstyle="text-align: left;">onion</td>
<tdstyle="text-align: center;">23,649</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Hkl</td>
<tdstyle="text-align: left;">yesod</td>
<tdstyle="text-align: center;">23,304</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">express</td>
<tdstyle="text-align: center;">22,856</td>
<tdstyle="text-align: left;">>5×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">play-scala</td>
<tdstyle="text-align: center;">22,372</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav g</td>
<tdstyle="text-align: left;">rizzly-jersey</td>
<tdstyle="text-align: center;">20,550</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">tornado</td>
<tdstyle="text-align: center;">20,372</td>
<tdstyle="text-align: left;">>6×</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">phalcon</td>
<tdstyle="text-align: center;">18,481</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Grv</td>
<tdstyle="text-align: left;">grails</td>
<tdstyle="text-align: center;">18,467</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">plack</td>
<tdstyle="text-align: center;">16,647</td>
<tdstyle="text-align: left;">>7×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">yaf</td>
<tdstyle="text-align: center;">14,388</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Medium</td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">hapi</td>
<tdstyle="text-align: center;">11,235</td>
<tdstyle="text-align: left;">>10×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play1</td>
<tdstyle="text-align: center;">9,979</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Hkl</td>
<tdstyle="text-align: left;">snap</td>
<tdstyle="text-align: center;">9,196</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">kelp</td>
<tdstyle="text-align: center;">8,250</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">flask</td>
<tdstyle="text-align: center;">8,167</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play-java</td>
<tdstyle="text-align: center;">7,905</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav p</td>
<tdstyle="text-align: left;">lay-java-jpa</td>
<tdstyle="text-align: center;">7,846</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">micromvc</td>
<tdstyle="text-align: center;">7,387</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">dancer</td>
<tdstyle="text-align: center;">5,040</td>
<tdstyle="text-align: left;">>20×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">mojolicious</td>
<tdstyle="text-align: center;">4,371</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">ringo-conv</td>
<tdstyle="text-align: center;">4,249</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">django</td>
<tdstyle="text-align: center;">4,026</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">codeigniter</td>
<tdstyle="text-align: center;">3,809</td>
<tdstyle="text-align: left;">>30×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;">Bad</td>
<tdstyle="text-align: left;">Rby</td>
<tdstyle="text-align: left;">rails</td>
<tdstyle="text-align: center;">3,445</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">lift</td>
<tdstyle="text-align: center;">3,311</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">slim</td>
<tdstyle="text-align: center;">3,112</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">kohana</td>
<tdstyle="text-align: center;">2,378</td>
<tdstyle="text-align: left;">>40×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">silex</td>
<tdstyle="text-align: center;">2,364</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Very Bad</td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">laravel</td>
<tdstyle="text-align: center;">1,639</td>
<tdstyle="text-align: left;">>60×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">phreeze</td>
<tdstyle="text-align: center;">1,410</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">lithium</td>
<tdstyle="text-align: center;">1,410</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">fuel</td>
<tdstyle="text-align: center;">1,410</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">cake</td>
<tdstyle="text-align: center;">1,287</td>
<tdstyle="text-align: left;">>80×</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">symfony2</td>
<tdstyle="text-align: center;">879</td>
<tdstyle="text-align: left;">>100×</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">aspnet-mvc</td>
<tdstyle="text-align: center;">871</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Rby</td>
<tdstyle="text-align: left;">sinatra</td>
<tdstyle="text-align: center;">561</td>
<tdstyle="text-align: left;">>200×</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">servicestack</td>
<tdstyle="text-align: center;">51</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Dar</td>
<tdstyle="text-align: left;">dart</td>
<tdstyle="text-align: center;">0</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">nancy</td>
<tdstyle="text-align: center;">0</td>
<tdstyle="text-align: left;"></td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">web-simple</td>
<tdstyle="text-align: center;">0</td>
<tdstyle="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>
<h1id="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 <ahref="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>
<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 don’t believe it is the standard. Javascript oriented framework score very badly regarding expressiveness.</p>
<span>Click here to show/hide the table for frameworks</span>
</div>
<divid="expressiveness-table">
<table>
<thead>
<trclass="header">
<thstyle="text-align: left;">Cluster</th>
<thstyle="text-align: left;">Language</th>
<thstyle="text-align: left;">Framework</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<tdstyle="text-align: left;">Excellent</td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">luminus</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">http-kit</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">compojure</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Hkl</td>
<tdstyle="text-align: left;">snap</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Hkl</td>
<tdstyle="text-align: left;">yesod</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Very Good</td>
<tdstyle="text-align: left;">Erl</td>
<tdstyle="text-align: left;">elli</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Erl</td>
<tdstyle="text-align: left;">cowboy</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">go</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">revel</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Grv</td>
<tdstyle="text-align: left;">grails</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">lift</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">finagle</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">scalatra</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">play-scala</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">play-slick</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">unfiltered</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;">Medium</td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">kelp</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">plack</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">dancer</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">web-simple</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">mojolicious</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">flask</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">django</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">tornado</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Rby</td>
<tdstyle="text-align: left;">rails</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Rby</td>
<tdstyle="text-align: left;">sinatra</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;">Bad</td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">nancy</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">aspnet-mvc</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">servicestack</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C++</td>
<tdstyle="text-align: left;">cpoll-pool</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C++</td>
<tdstyle="text-align: left;">cpoll-cppsp</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Dar</td>
<tdstyle="text-align: left;">dart</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play1</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">vertx</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">gemini</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">spring</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">wicket</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">servlet</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">tapestry</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play-java</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">dropwizard</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">rest-express</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play-java-jpa</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">grizzly-jersey</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Lua</td>
<tdstyle="text-align: left;">openresty</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">php</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">yaf</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">cake</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">fuel</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">slim</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">silex</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">kohana</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">laravel</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">lithium</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">phalcon</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">phreeze</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">micromvc</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">symfony2</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">codeigniter</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Very Bad</td>
<tdstyle="text-align: left;">C</td>
<tdstyle="text-align: left;">onion</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">hapi</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">ringo</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">nodejs</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">express</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">ringo-conv</td>
</tr>
</tbody>
</table>
</div>
<h3id="robustness">Robustness</h3>
<p>I couldn’t 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 doesn’t 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>
<imgsrc="/Scratch/img/blog/Rational-Web-Framework-Choice/languagesafety.png"alt="Static Type Properties from [James IRY Blog][typesanalysis]"/>
<figcaption>
Static Type Properties from <ahref="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>
<trclass="odd">
<tdstyle="text-align: left;">Excellent</td>
<td>Haskell, Scheme, Erlang</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Very Good</td>
<td>Scala, Java, Clojure</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;">Good</td>
<td>Ruby, Python, Groovy, javascript, PHP</td>
</tr>
<trclass="even">
<tdstyle="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>
<divid="toggle-robustness-table"class="button">
<span>Click here to show/hide the table for frameworks</span>
</div>
<divid="robustness-table">
<table>
<thead>
<trclass="header">
<thstyle="text-align: left;">Cluster</th>
<thstyle="text-align: left;">Language</th>
<thstyle="text-align: left;">Framework</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<tdstyle="text-align: left;">Excellent</td>
<tdstyle="text-align: left;">Erl</td>
<tdstyle="text-align: left;">elli</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Erl</td>
<tdstyle="text-align: left;">cowboy</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Hkl</td>
<tdstyle="text-align: left;">snap</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Hkl</td>
<tdstyle="text-align: left;">yesod</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;">Very Good</td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">luminus</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">http-kit</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Clj</td>
<tdstyle="text-align: left;">compojure</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play1</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">vertx</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">gemini</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">spring</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">wicket</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">servlet</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">tapestry</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play-java</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">dropwizard</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">rest-express</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">play-java-jpa</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Jav</td>
<tdstyle="text-align: left;">grizzly-jersey</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">lift</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">finagle</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">scalatra</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">play-scala</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">play-slick</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Sca</td>
<tdstyle="text-align: left;">unfiltered</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Good</td>
<tdstyle="text-align: left;">Grv</td>
<tdstyle="text-align: left;">grails</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">hapi</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">ringo</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">nodejs</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">express</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">JS</td>
<tdstyle="text-align: left;">ringo-conv</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Lua</td>
<tdstyle="text-align: left;">openresty</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">php</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">yaf</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">cake</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">fuel</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">slim</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">silex</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">kohana</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">laravel</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">lithium</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">phalcon</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">phreeze</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">micromvc</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">symfony2</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">PHP</td>
<tdstyle="text-align: left;">codeigniter</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">flask</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">django</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Py</td>
<tdstyle="text-align: left;">tornado</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Rby</td>
<tdstyle="text-align: left;">rails</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Rby</td>
<tdstyle="text-align: left;">sinatra</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;">Medium</td>
<tdstyle="text-align: left;">C</td>
<tdstyle="text-align: left;">onion</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">nancy</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">aspnet-mvc</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C#</td>
<tdstyle="text-align: left;">servicestack</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C++</td>
<tdstyle="text-align: left;">cpoll-pool</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">C++</td>
<tdstyle="text-align: left;">cpoll-cppsp</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Dar</td>
<tdstyle="text-align: left;">dart</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">go</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Go</td>
<tdstyle="text-align: left;">revel</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">kelp</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">plack</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">dancer</td>
</tr>
<trclass="even">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">web-simple</td>
</tr>
<trclass="odd">
<tdstyle="text-align: left;"></td>
<tdstyle="text-align: left;">Prl</td>
<tdstyle="text-align: left;">mojolicious</td>
</tr>
</tbody>
</table>
</div>
<h2id="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 didn’t 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>
<tableid="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>
<trid="t-expressiveness">
<th>
Expressiveness
</th>
</tr>
<trid="t-popularity">
<th>
Popularity
</th>
</tr>
<trid="t-efficiency">
<th>
Efficiency
</th>
</tr>
<trid="t-robustness">
<th>
Robustness
</th>
</tr>
</table>
<divid="compute"class="button">
<span>Click to force refresh</span>
</div>
<divid="result">
</div>
<script>// <![CDATA[ // <![CDATA[
function lt(x,y){return (x < y);}
function bal(balname,str){return '<'+balname+'>'+str+'</'+balname+'>';}
function ret(){return '<br/>';}
// ]]> // ]]></script>
<script>// <![CDATA[
String.prototype.repeat = function(num){return new Array(num+1).join(this);};
<p>I didn’t 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 <spanclass="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>
<h2id="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 shouldn’t 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>
<p>Ce site web est fait avec <ahref="http://jaspervdj.be/hakyll">Hakyll</a>.</p>
<p><ahref="http://jaspervdj.be/hakyll">Hakyll</a> peut être vu comme un <spanclass="sc"><abbrtitle="Content Management System">cms</abbr></span> minimaliste. D’une façon plus générale, il s’agit d’une bibliothèque qui facilite la création automatique de fichiers.</p>
<p>D’un point de vue utilisateur voici comment j’écris mes articles :</p>
<oltype="1">
<li>J’ouvre un éditeur de texte (vim dans mon cas). J’édite un fichier markdow qui ressemble à ça :</li>
</ol>
<divclass="sourceCode"id="cb1"><preclass="sourceCode markdown"><codeclass="sourceCode markdown"><aclass="sourceLine"id="cb1-1"title="1">Un titre de page</a>
<aclass="sourceLine"id="cb1-19"title="19"><spanclass="dt">> ## C'est un H2 dans un blockquote</span></a></code></pre></div>
<olstart="2"type="1">
<li>J’ouvre 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 <ahref="http://github.com">github</a>.</li>
</ol>
<p>A ne pas y regarder de trop près, on peut réduire le rôle d’Hakyll à :</p>
<blockquote>
<p>Créer (resp. mettre à jour) un fichier <spanclass="sc"><abbrtitle="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 :</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 <spanclass="sc"><abbrtitle="Rich Site Summary">rss</abbr></span></li>
<li>Filtrer le contenu</li>
<li>Gérer les dépendances</li>
</ul>
<p>Le travail d’Hakyll est de vous aider avec tout ça. Commençons par expliquer les concepts basiques.</p>
<h2id="les-concepts-et-la-syntaxe">Les concepts et la syntaxe</h2>
<p>Pour chaque fichier que vous créer, il faut fournir :</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 :</p>
<divclass="sourceCode"id="cb2"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb2-1"title="1"><spanclass="co">-- pour chaque fichier dans le répertoire static</span></a>
<p>Ce programme va copier <code>static/foo.jpg</code> dans <code>_site/static/foo.jpg</code>. C’est un peu lourd pour un simple <code>cp</code>. Maintenant comment faire pour transformer automatiquement un fichier markdown dans le bon <spanclass="sc"><abbrtitle="HyperText Markup Language">html</abbr></span>?</p>
<divclass="sourceCode"id="cb3"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb3-1"title="1"><spanclass="co">-- pour chaque fichier avec un extension md</span></a>
<p>Mais horreur ! <code>_site/posts/cthulhu.html</code> n’est pas un <spanclass="sc"><abbrtitle="HyperText Markup Language">html</abbr></span> complet. Il ne possède ni header, ni footer, etc… C’est ici que nous utilisons des templates. J’ajoute une nouvelle directive dans le bloc “compile”.</p>
<p>C’est 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 d’utiliser les <code>Context</code>s. Pour cela, nous devrons ajouter des <em>metadonnées</em> à notre markdown<ahref="#fn1"class="footnote-ref"id="fnref1"><sup>1</sup></a>.</p>
<li>create an <spanclass="sc"><abbrtitle="Rich Site Summary">rss</abbr></span> feed?</li>
<li>filter the content?</li>
<li>add abbreviations support?</li>
<li>manage two languages?</li>
</ul>
<h3id="use-sass">Use SASS</h3>
<p>That’s easy. Simply call the executable using <code>unixFilter</code>. Of course you’ll have to install SASS (<code>gem install sass</code>). And we also use compressCss to gain some space.</p>
<p>In order to help to reference your website on the web, it is nice to add some keywords as meta datas to your <spanclass="sc"><abbrtitle="HyperText Markup Language">html</abbr></span> page.</p>
<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 <spanclass="sc"><abbrtitle="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>
<divclass="sourceCode"id="cb13"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb13-1"title="1"><spanclass="co">-- metaKeywordContext will return a Context containing a String</span></a>
<aclass="sourceLine"id="cb13-14"title="14"> showMetaTags t <spanclass="ot">=</span><spanclass="st">"<meta name=\"keywords\" content=\""</span></a>
<aclass="sourceLine"id="cb13-15"title="15"><spanclass="op">++</span> t <spanclass="op">++</span><spanclass="st">"\">\n"</span></a></code></pre></div>
<p>Then we pass this <code>Context</code> to the <code>loadAndApplyTemplate</code> function:</p>
<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>
<divclass="sourceCode"id="cb17"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb17-1"title="1"><spanclass="co">-- replace a foo/bar.md by foo/bar/index.html</span></a>
<aclass="sourceLine"id="cb17-2"title="2"><spanclass="co">-- this way the url looks like: foo/bar in most browsers</span></a>
<aclass="sourceLine"id="cb17-7"title="7"> takeDirectory p <spanclass="op"></></span> takeBaseName p <spanclass="op"></></span><spanclass="st">"index.html"</span></a>
<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>
<divclass="sourceCode"id="cb18"><preclass="sourceCode haskell"><codeclass="sourceCode haskell"><aclass="sourceLine"id="cb18-1"title="1"><spanclass="co">-- replace url of the form foo/bar/index.html by foo/bar</span></a>
<h3id="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 didn’t want to change my <spanclass="sc"><abbrtitle="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>
<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 <spanclass="sc"><abbrtitle="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>
<p><code>postList</code> returns an <spanclass="sc"><abbrtitle="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>
<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>
<p>It wasn’t so easy. But it works pretty well.</p>
<h3id="create-an-rss-feed">Create an <spanclass="sc"><abbrtitle="Rich Site Summary">rss</abbr></span> feed</h3>
<p>To create an <spanclass="sc"><abbrtitle="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 <spanclass="sc"><abbrtitle="HyperText Markup Language">html</abbr></span> rendering and another time for <spanclass="sc"><abbrtitle="Rich Site Summary">rss</abbr></span>. Remark we need to generate the <spanclass="sc"><abbrtitle="Rich Site Summary">rss</abbr></span> version to create the <spanclass="sc"><abbrtitle="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>
<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 don’t 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>
<aclass="sourceLine"id="cb28-3"title="3"> { feedTitle <spanclass="ot">=</span><spanclass="st">"Great Old Ones"</span></a>
<aclass="sourceLine"id="cb28-4"title="4"> , feedDescription <spanclass="ot">=</span><spanclass="st">"This feed provide information about Great Old Ones"</span></a>
<p>Great idea certainly steal from <ahref="http://nanoc.ws">nanoc</a> (my previous blog engine)!</p>
<h3id="filter-the-content">Filter the content</h3>
<p>As I just said, <ahref="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 don’t 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 -> String</code>.</p>
<p>Also we generally want prefilters (to filter the markdown) and postfilters (to filter the <spanclass="sc"><abbrtitle="HyperText Markup Language">html</abbr></span> after the pandoc compilation).</p>
<p>Comparing to <spanstyle="text-transform: uppercase">L<supstyle="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<substyle="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>
<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>each time I write <spanstyle="text-transform: uppercase">L<supstyle="vertical-align: 0.15em; margin-left: -0.36em; margin-right: -0.15em; font-size: .85em">a</sup>T<substyle="vertical-align: -0.5ex; margin-left: -0.1667em; margin-right: -0.125em; font-size: 1em">e</sub>X</span>?</p>
<h3id="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>
<aclass="sourceLine"id="cb35-11"title="11"><spanclass="dt">Nothing</span><spanclass="ot">-></span><spanclass="fu">return</span> (<spanclass="st">"NO TRANSLATION FOR "</span><spanclass="op">++</span> name)</a>
<aclass="sourceLine"id="cb35-12"title="12"><spanclass="dt">Nothing</span><spanclass="ot">-></span><spanclass="fu">return</span> (<spanclass="st">"NO TRANSLATION FOR "</span><spanclass="op">++</span> name)</a></code></pre></div>
<h2id="conclusion">Conclusion</h2>
<p>The full code is <ahref="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>
<oltype="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 didn’t 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>
<liid="fn1"><p>Nous pouvons aussi ajouter ces métadonnées dans un fichier externe (<code>toto.md.metadata</code>).<ahref="#fnref1"class="footnote-back">↩</a></p></li>
</ol>
</section>]]></summary>
</entry>
<entry>
<title>Être correct avec les boutons share</title>
<p><spanclass="sc"><abbrtitle="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 n’avez pas envie de lire, copiez et collez simplement le code suivant dans votre <spanclass="sc"><abbrtitle="HyperText Markup Language">html</abbr></span> :</p>
<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 don’t 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 <spanclass="sc"><abbrtitle="In my Humble Opinion">imho</abbr></span>) this isn’t 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 won’t 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 doesn’t 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>
<h2id="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>doesn’t follow your user,</li>
<li>use almost no computer ressource,</li>
<li>doesn’t slow down your website,</li>
<li>doesn’t execute any third party js on your website.</li>
</ul></li>
<li>Cons:
<ul>
<li>doesn’t provide any popularity information.</li>
<p>If you don’t want to write the <spanclass="sc"><abbrtitle="Uniform Ressource Locator">url</abbr></span> yourself, you could use some minimal js:</p>
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>
<h2id="conclusion">Conclusion</h2>
<oltype="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>
<p>Yesterday I was happy to make a presentation about Category Theory at <ahref="http://www.meetup.com/riviera-scala-clojure">Riviera Scala Clojure Meetup</a> (note I used only Haskell for my examples).</p>
<imgsrc="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/categlory.jpg"alt="Cat n glory"/><figcaption>credit to Tokuhiro Kawai (川井徳寛)</figcaption>
<imgsrc="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/eilenberg.gif"alt="Samuel Eilenberg"/><imgsrc="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/maclaine.jpg"alt="Saunders Mac Lane"/>
★: <ahref="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/> ☆: <ahref="http://math.ucr.edu/home/baez/rosetta.pdf">Physics, Topology, Logic and Computation: A Rosetta Stone, John C. Baez, Mike Stay, 2009</a>
</p>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="from-a-programmer-perspective">From a Programmer perspective</h2>
<blockquote>
<p>Category Theory is a new language/framework for Math</p>
<imgclass="right"style="max-width:17%"src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/strings.png"alt="Monoids are one object categories"/>
<imgclass="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><imgclass="right"alt="isomorph cats"src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/isomorph-cats.jpg"/><emclass="orange">isomorphism</em>: \(f:A→B\) which can be "undone"<em>i.e.</em><br/>\(∃g:B→A\), \(g∘f=id_A\) <spanclass="and">&</span> \(f∘g=id_B\)<br/>in this case, \(A\) <spanclass="and">&</span> \(B\) are <emclass="orange">isomorphic</em>.</p>
<p><spanclass="orange">A≌B</span> means A and B are essentially the same.<br/>In Category Theory, <spanclass="orange">=</span> is in fact mostly <spanclass="orange">≌</span>.<br/>For example in commutative diagrams.</p>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2>Functor</h2>
<p> A functor is a mapping between two categories.
Let \(\C\) and \(\D\) be two categories.
A <em>functor</em><spanclass="orange">\(\F\)</span> from <spanclass="blue">\(\C\)</span> to <spanclass="green">\(\D\)</span>:</p>
<ul>
<li> Associate objects: <spanclass="backblue">\(A\in\ob{\C}\)</span> to <spanclass="backgreen">\(\F(A)\in\ob{\D}\)</span></li>
<p>Forget glitches because of <code>undefined</code>.</p>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="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 :: * -> *
(,), (->) :: * -> * -> *
[Int], Maybe Char, Maybe [Int] :: *</code></pre>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="haskell-types">Haskell Types</h2>
<p>Sometimes, the type determine a lot about the function<sup>★</sup>:</p>
<preclass="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 <spanclass="red">(+1)</span> l
-- The (+1) force 'a' to be a Num.</code></pre>
<p>
<p><spanclass="small base01">★:<ahref="http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf">Theorems for free!, Philip Wadler, 1989</a></span></p>
<divclass="flush"></div></section>
<sectionclass="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
<imgwidth="50%"src="http://yogsototh.github.io/Category-Theory-Presentation/categories/img/mp/cat-hask-endofunctor.png"alt="Category of Hask endofunctors"/>
<h2id="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>
<pre><codeclass="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>
<pre><codeclass="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>
<pre><codeclass="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>
<pre><codeclass="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>
<imgstyle="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 <spanclass="red">no isomorphism</span>.<br/> Hint: <code>Bool</code> lists longer than 1. </figcaption>
<p>Goal, find: <code>◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)</code><br/><code>f :: a -> F b</code>, <code>g :: b -> 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>
<p>Goal, find: <code>◎ :: (b -> F c) -> (a -> F b) -> (a -> F c)</code><br/><code>f :: a -> F b</code>, <code>g :: b -> F c</code>, <spanclass="orange"><code>f x :: F b</code></span>:</p>
<ul>
<li>Use <code>fmap :: (t -> u) -> (F t -> F u)</code>!</li>
<li><code>(fmap g) :: F b -> 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) -> F c</code></li>
<li><code>(g ◎ f) x = join ((fmap g) (f x))</code> ☺<br/>◎ is the Kleisli composition; in Haskell: <code><=<</code> (in <code>Control.Monad</code>).</li>
</ul>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="necessary-laws">Necessary laws</h2>
<p>For ◎ to work like composition, we need join to hold the following properties:</p>
<li>abusing notations denoting <code>join</code> by ⊙; this is equivalent to<br/><spanclass="orange"><code>(F ⊙ F) ⊙ F = F ⊙ (F ⊙ F)</code></span></li>
<li>There exists <code>η :: a -> F a</code> s.t.<br/><spanclass="orange"><code>η⊙F=F=F⊙η</code></span></li>
<p>A monad is a triplet <code>(M,⊙,η)</code> where</p>
<ul>
<li>\(M\) an <spanclass="orange">Endofunctor</span> (to type <code>a</code> associate <code>M a</code>)</li>
<li>\(⊙:M×M→M\) a <spanclass="orange">nat. trans.</span> (i.e. <code>⊙::M (M a) → M a</code> ; <code>join</code>)</li>
<li>\(η:I→M\) a <spanclass="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>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="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>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="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>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="example-list">Example: List</h2>
<ul>
<li><code>[] :: * -> *</code> an <spanclass="orange">Endofunctor</span></li>
<li>\(⊙:M×M→M\) a nat. trans. (<code>join :: M (M a) -> M a</code>)</li>
<li>\(η:I→M\) a nat. trans.</li>
</ul>
<preclass="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>
<divclass="flush"></div></section>
<sectionclass="slide">
<h2id="example-list-law-verification">Example: List (law verification)</h2>
<p>Example: <code>List</code> is a functor (<code>join</code> is ⊙)</p>