her.esy.fun/src/Scratch/en/blog/Holy-Haskell-Starter/index.html

960 lines
98 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>YBlog - Holy Haskell Project Starter</title>
<meta name="keywords" content="programming" />
<link rel="shortcut icon" type="image/x-icon" href="../../../../Scratch/img/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/css/y.css" />
<link rel="stylesheet" type="text/css" href="/css/legacy.css" />
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon" href="../../../../Scratch/img/about/FlatAvatar@2x.png" />
<!--[if lt IE 9]>
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
<![endif]-->
<!-- IndieAuth -->
<link href="https://twitter.com/yogsototh" rel="me">
<link href="https://github.com/yogsototh" rel="me">
<link href="mailto:yann.esposito@gmail.com" rel="me">
<link rel="pgpkey" href="../../../../pubkey.txt">
</head>
<body lang="en" class="article">
<div id="content">
<div id="header">
<div id="choix">
<span id="choixlang">
<a href="../../../../Scratch/fr/blog/Holy-Haskell-Starter/">French</a>
</span>
<span class="tomenu"><a href="#navigation">↓ Menu ↓</a></span>
<span class="flush"></span>
</div>
</div>
<div id="titre">
<h1>Holy Haskell Project Starter</h1>
<h2>A Haskell tutorial: from nothing to something useful</h2>
</div>
<div class="flush"></div>
<div id="afterheader" class="article">
<div class="corps">
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/holy-grail-monty-python.jpg" alt="Monty Python Holy Grail" />
</div>
<div class="intro">
<p><span class="sc"><abbr title="Too long; didn't read">tl;dr</abbr>: </span> Learn how to start a new Haskell project. Translate a starter tool written in <code>zsh</code> in Haskell using its own result.</p>
<blockquote>
<p>“Good Sir Knight, will you come with me to Camelot, and join us at the Round Table?”</p>
</blockquote>
<p>In order to work properly with Haskell you need to initialize your environment. Typically, you need to use a cabal file, create some test for your code. Both, unit test and propositional testing (random and exhaustive up to a certain depth). You need to use <code>git</code> and generally hosting it on github. Also, it is recommended to use cabal sandboxes. And as bonus, an auto-update tool that recompile and retest on each file save.</p>
<p>In this article, we will create such an environment using a zsh script. Then we will write a Haskell project which does the same work as the zsh script. You will then see how to work in such an environment.</p>
<p>If you are starting to understand Haskell but consider yourself a beginner, this tutorial will show you how to make a real application using quite surprisingly a lot of features:</p>
<ul>
<li>use colorized output</li>
<li>interact with a user in command line</li>
<li>read/write files</li>
<li>kind of parse a file (in fact, simply split it)</li>
<li>use a templating system (mustache: fill a data structure, write files)</li>
<li>make a HTTP GET request then parse the JSON answer and use it</li>
<li>use random</li>
<li>create a cabal package</li>
<li>add and use non source files to a cabal package</li>
<li>Test your code (both unit testing and property testing)</li>
</ul>
<p><strong></strong> zsh is by its nature more suitable to file manipulation. But the Haskell code is clearly more organized while quite terse for a multi-purpose language.</p>
<p><strong></strong> holy-project is on hackage. It can be installed with <code>cabal update &amp;&amp; cabal install holy-project</code>.</p>
</div>
<p>I recently read this excellent article: <a href="http://jabberwocky.eu/2013/10/24/how-to-start-a-new-haskell-project/">How to Start a New Haskell Project</a>.</p>
<p>While the article is very good, I lacked some minor informations<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a>. Inspired by it, I created a simple script to initialize a new Haskell project. During the process I improved some things a bit.</p>
<p>If you want to use this script, the steps are:</p>
<ol type="1">
<li><a href="http://wwW.haskell.org/platform">Install Haskell</a></li>
<li>Make sure you have the latest <code>cabal-install</code> (at least 1.18)</li>
</ol>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb1-1" title="1"><span class="op">&gt;</span> <span class="ex">cabal</span> install cabal-install</a></code></pre></div>
<ol start="3" type="1">
<li>Download and run the script</li>
</ol>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb2-1" title="1"><span class="co"># Download the script</span></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="fu">git</span> clone https://github.com/yogsototh/init-haskell-project.git</a>
<a class="sourceLine" id="cb2-3" title="3"><span class="co"># Copy the script in a directory of you PATH variable</span></a>
<a class="sourceLine" id="cb2-4" title="4"><span class="fu">cp</span> init-haskell-project/holy-haskell.sh ~/bin</a>
<a class="sourceLine" id="cb2-5" title="5"><span class="co"># Go to the directory containing all your projects</span></a>
<a class="sourceLine" id="cb2-6" title="6"><span class="bu">cd</span> my/projects/directory</a>
<a class="sourceLine" id="cb2-7" title="7"><span class="co"># Launch thcript</span></a>
<a class="sourceLine" id="cb2-8" title="8"><span class="ex">holy-haskell.sh</span></a></code></pre></div>
<p>What does this script do that <code>cabal init</code> doesnt do?</p>
<ul>
<li>Use cabal sandbox</li>
<li>It initialize <code>git</code> with the right <code>.gitignore</code> file.</li>
<li>Use <code>tasty</code> to organize your tests (HUnit, QuickCheck and SmallCheck).</li>
<li>Use <code>-Wall</code> for <code>ghc</code> compilation.</li>
<li>Will make references to Holy Grail</li>
<li>Search your default github username via <a href="http://developer.github.com/v3/search/#search-users">github api</a>.</li>
</ul>
<h2 id="zsh-really"><code>zsh</code> really?</h2>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/french-insult.jpg" alt="French insult" />
</div>
<p>Developing the script in <code>zsh</code> was easy. But considering its size, it is worth to rewrite it in Haskell. Furthermore, it will be a good exercise.</p>
<h3 id="patricide">Patricide</h3>
<p>In a first time, we initialize a new Haskell project with <code>holy-haskell.sh</code>:</p>
<pre>
> ./holy-haskell.sh
<span class="green">Bridgekeeper: Stop!
Bridgekeeper: Who would cross the Bridge of Death
Bridgekeeper: must answer me these questions three,
Bridgekeeper: ere the other side he see.</span>
<span class="yellow">You: Ask me the questions, bridgekeeper, I am not afraid.</span>
<span class="green">Bridgekeeper: What is the name of your project?</span>
> Holy project
<span class="green">Bridgekeeper: What is your name?</span> (Yann Esposito (Yogsototh))
>
<span class="green">Bridgekeeper: What is your email?</span> (Yann.Esposito@gmail.com)
>
<span class="green">Bridgekeeper: What is your github user name?</span> (yogsototh)
>
<span class="green">Bridgekeeper: What is your project in less than ten words?</span>
> Start your Haskell project with cabal, git and tests.
Initialize git
Initialized empty Git repository in .../holy-project/.git/
Create files
.gitignore
holy-project.cabal
Setup.hs
LICENSE (MIT)
test/Test.hs
test/HolyProject/Swallow/Test.hs
src/HolyProject/Swallow.hs
test/HolyProject/Coconut/Test.hs
src/HolyProject/Coconut.hs
src/HolyProject.hs
src/Main.hs
Cabal sandboxing, install and test
...
many compilations lines
...
Running 1 test suites...
Test suite Tests: RUNNING...
Test suite Tests: PASS
Test suite logged to: dist/test/holy-project-0.1.0.0-Tests.log
1 of 1 test suites (1 of 1 test cases) passed.
All Tests
Swallow
swallow test: <span class="green">OK</span>
coconut
coconut: <span class="green">OK</span>
coconut property: <span class="green">OK</span>
148 tests completed
<span class="green">All 3 tests passed</span>
<span class="green">Bridgekeeper: What... is the air-speed velocity of an unladen swallow?</span>
<span class="yellow">You: What do you mean? An African or European swallow?</span>
<span class="green">Bridgekeeper: Huh? I... I don't know that.</span>
[the bridgekeeper is thrown over]
<span class="green">Bridgekeeper: Auuuuuuuuuuuugh</span>
Sir Bedevere: How do you know so much about swallows?
<span class="yellow">You: Well, you have to know these things when you're a king, you know.</span>
</pre>
<p>The different steps are:</p>
<ul>
<li>small introduction quotes</li>
<li>ask five questions <em>three question sir…</em></li>
<li>create the directory for the project</li>
<li>init git</li>
<li>create files</li>
<li>sandbox cabal</li>
<li>cabal install and test</li>
<li>run the test directly in the terminal</li>
<li>small goodbye quotes</li>
</ul>
<p>Features to note:</p>
<ul>
<li>color in the terminal</li>
<li>check some rules on the project name</li>
<li>random message if error</li>
<li>use <code>~/.gitconfig</code> file in order to provide a default name and email.</li>
<li>use the github API which returns JSON to get the default github user name.</li>
</ul>
<p>So, apparently nothing too difficult to achieve.</p>
<p>We should now have an initialized Haskell environment for us to work. The first thing you should do, is to go into this new directory and launch ./auto-update in some terminal. I personally use <code>tmux</code> on Linux or the splits in <code>iTerm 2</code> on Mac OS X. Now, any modification of a source file will relaunch a compilation and a test.</p>
<h3 id="the-dialogs">The dialogs</h3>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/bridge-of-death.jpg" alt="Bridge of Death" />
</div>
<p>To print the introduction text in <code>zsh</code>:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb3-1" title="1"><span class="co"># init colors</span></a>
<a class="sourceLine" id="cb3-2" title="2"><span class="ex">autoload</span> colors</a>
<a class="sourceLine" id="cb3-3" title="3"><span class="ex">colors</span></a>
<a class="sourceLine" id="cb3-4" title="4"><span class="kw">for</span> <span class="ex">COLOR</span> in RED GREEN YELLOW BLUE MAGENTA CYAN BLACK WHITE<span class="kw">;</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb3-5" title="5"> <span class="bu">eval</span> <span class="va">$COLOR</span>=<span class="st">'$fg_no_bold[${(L)COLOR}]'</span></a>
<a class="sourceLine" id="cb3-6" title="6"> <span class="bu">eval</span> BOLD_<span class="va">$COLOR</span>=<span class="st">'$fg_bold[${(L)COLOR}]'</span></a>
<a class="sourceLine" id="cb3-7" title="7"><span class="kw">done</span></a>
<a class="sourceLine" id="cb3-8" title="8"><span class="bu">eval</span> RESET=<span class="st">'$reset_color'</span></a>
<a class="sourceLine" id="cb3-9" title="9"><span class="co"># functions</span></a>
<a class="sourceLine" id="cb3-10" title="10"><span class="fu">bk()</span>{<span class="ex">print</span> -- <span class="st">&quot;</span><span class="va">${GREEN}</span><span class="st">Bridgekeeper: </span><span class="va">$*${RESET}</span><span class="st">&quot;</span>}</a>
<a class="sourceLine" id="cb3-11" title="11"><span class="fu">bkn()</span>{<span class="ex">print</span> -n -- <span class="st">&quot;</span><span class="va">${GREEN}</span><span class="st">Bridgekeeper: </span><span class="va">$*${RESET}</span><span class="st">&quot;</span>}</a>
<a class="sourceLine" id="cb3-12" title="12"><span class="fu">you()</span>{<span class="ex">print</span> -- <span class="st">&quot;</span><span class="va">${YELLOW}</span><span class="st">You: </span><span class="va">$*${RESET}</span><span class="st">&quot;</span>}</a>
<a class="sourceLine" id="cb3-13" title="13"><span class="ex">...</span></a>
<a class="sourceLine" id="cb3-14" title="14"><span class="co"># the introduction dialog</span></a>
<a class="sourceLine" id="cb3-15" title="15"><span class="ex">bk</span> <span class="st">&quot;Stop!&quot;</span></a>
<a class="sourceLine" id="cb3-16" title="16"><span class="ex">bk</span> <span class="st">&quot;Who would cross the Bridge of Death&quot;</span></a>
<a class="sourceLine" id="cb3-17" title="17"><span class="ex">bk</span> <span class="st">&quot;must answer me these questions three,&quot;</span></a>
<a class="sourceLine" id="cb3-18" title="18"><span class="ex">bk</span> <span class="st">&quot;ere the other side he see.&quot;</span></a>
<a class="sourceLine" id="cb3-19" title="19"><span class="ex">you</span> <span class="st">&quot;Ask me the questions, bridgekeeper, I am not afraid.\n&quot;</span></a>
<a class="sourceLine" id="cb3-20" title="20"><span class="ex">...</span></a>
<a class="sourceLine" id="cb3-21" title="21"><span class="co"># the final dialog</span></a>
<a class="sourceLine" id="cb3-22" title="22"><span class="ex">print</span> <span class="st">&quot;\n\n&quot;</span></a>
<a class="sourceLine" id="cb3-23" title="23"><span class="ex">bk</span> <span class="st">&quot;What... is the air-speed velocity of an unladen swallow?&quot;</span></a>
<a class="sourceLine" id="cb3-24" title="24"><span class="ex">you</span> <span class="st">&quot;What do you mean? An African or European swallow?&quot;</span></a>
<a class="sourceLine" id="cb3-25" title="25"><span class="ex">bk</span> <span class="st">&quot;Huh? I... I don't know that.&quot;</span></a>
<a class="sourceLine" id="cb3-26" title="26"><span class="ex">log</span> <span class="st">&quot;[the bridgekeeper is thrown over]&quot;</span></a>
<a class="sourceLine" id="cb3-27" title="27"><span class="ex">bk</span> <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb3-28" title="28"><span class="ex">log</span> <span class="st">&quot;Sir Bedevere: How do you know so much about swallows?&quot;</span></a>
<a class="sourceLine" id="cb3-29" title="29"><span class="ex">you</span> <span class="st">&quot;Well, you have to know these things when you're a king, you know.&quot;</span></a></code></pre></div>
<p>In the first Haskell version I dont use colors. We see we can almost copy/paste. I just added the types.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb4-1" title="1"><span class="ot">bk ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-2" title="2">bk str <span class="ot">=</span> <span class="fu">putStrLn</span> <span class="op">$</span> <span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str</a>
<a class="sourceLine" id="cb4-3" title="3"></a>
<a class="sourceLine" id="cb4-4" title="4"><span class="ot">bkn ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-5" title="5">bkn str <span class="ot">=</span> pustStr <span class="op">$</span> <span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str</a>
<a class="sourceLine" id="cb4-6" title="6"></a>
<a class="sourceLine" id="cb4-7" title="7"><span class="ot">you ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-8" title="8">you str <span class="ot">=</span> <span class="fu">putStrLn</span> <span class="op">$</span> <span class="st">&quot;You: &quot;</span> <span class="op">++</span> str</a>
<a class="sourceLine" id="cb4-9" title="9"></a>
<a class="sourceLine" id="cb4-10" title="10"><span class="ot">intro ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-11" title="11">intro <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb4-12" title="12"> bk <span class="st">&quot;Stop!&quot;</span></a>
<a class="sourceLine" id="cb4-13" title="13"> bk <span class="st">&quot;Who would cross the Bridge of Death&quot;</span></a>
<a class="sourceLine" id="cb4-14" title="14"> bk <span class="st">&quot;must answer me these questions three,&quot;</span></a>
<a class="sourceLine" id="cb4-15" title="15"> bk <span class="st">&quot;ere the other side he see.&quot;</span></a>
<a class="sourceLine" id="cb4-16" title="16"> you <span class="st">&quot;Ask me the questions, bridgekeeper, I am not afraid.\n&quot;</span></a>
<a class="sourceLine" id="cb4-17" title="17"></a>
<a class="sourceLine" id="cb4-18" title="18"><span class="ot">end ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb4-19" title="19">end <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb4-20" title="20"> <span class="fu">putStrLn</span> <span class="st">&quot;\n\n&quot;</span></a>
<a class="sourceLine" id="cb4-21" title="21"> bk <span class="st">&quot;What... is the air-speed velocity of an unladen swallow?&quot;</span></a>
<a class="sourceLine" id="cb4-22" title="22"> you <span class="st">&quot;What do you mean? An African or European swallow?&quot;</span></a>
<a class="sourceLine" id="cb4-23" title="23"> bk <span class="st">&quot;Huh? I... I don't know that.&quot;</span></a>
<a class="sourceLine" id="cb4-24" title="24"> <span class="fu">putStrLn</span> <span class="st">&quot;[the bridgekeeper is thrown over]&quot;</span></a>
<a class="sourceLine" id="cb4-25" title="25"> bk <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb4-26" title="26"> <span class="fu">putStrLn</span> <span class="st">&quot;Sir Bedevere: How do you know so much about swallows?&quot;</span></a>
<a class="sourceLine" id="cb4-27" title="27"> you <span class="st">&quot;Well, you have to know these things when you're a king, you know.&quot;</span></a></code></pre></div>
<p>Now lets just add the colors using the <a href="http://hackage.haskell.org/package/ansi-terminal"><code>ansi-terminal</code></a> package. So we have to add <code>ansi-terminal</code> as a build dependency in our cabal file.</p>
<p>Edit <code>holy-project.cabal</code> to add it.</p>
<pre><code>...
build-depends: base &gt;=4.6 &amp;&amp; &lt;4.7
<span class="highlight">, ansi-terminal</span>
...</code></pre>
<p>Now look at the modified Haskell code:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb6-1" title="1"><span class="highlight"><span class="kw">import</span> <span class="dt">System.Console.ANSI</span></span></a>
<a class="sourceLine" id="cb6-2" title="2"></a>
<a class="sourceLine" id="cb6-3" title="3"><span class="ot">colorPutStr ::</span> <span class="dt">Color</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-4" title="4">colorPutStr color str <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb6-5" title="5"> setSGR [ <span class="dt">SetColor</span> <span class="dt">Foreground</span> <span class="dt">Dull</span> color</a>
<a class="sourceLine" id="cb6-6" title="6"> , <span class="dt">SetConsoleIntensity</span> <span class="dt">NormalIntensity</span></a>
<a class="sourceLine" id="cb6-7" title="7"> ]</a>
<a class="sourceLine" id="cb6-8" title="8"> <span class="fu">putStr</span> str</a>
<a class="sourceLine" id="cb6-9" title="9"> setSGR []</a>
<a class="sourceLine" id="cb6-10" title="10"></a>
<a class="sourceLine" id="cb6-11" title="11"></a>
<a class="sourceLine" id="cb6-12" title="12"><span class="ot">bk ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-13" title="13">bk str <span class="ot">=</span> <span class="highlight">colorPutStr <span class="dt">Green</span></span> (<span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str <span class="op">++</span> <span class="st">&quot;\n&quot;</span>)</a>
<a class="sourceLine" id="cb6-14" title="14"><span class="ot">bkn ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-15" title="15">bkn str <span class="ot">=</span> <span class="highlight">colorPutStr <span class="dt">Green</span></span> (<span class="st">&quot;Bridgekeeper: &quot;</span> <span class="op">++</span> str)</a>
<a class="sourceLine" id="cb6-16" title="16"><span class="ot">you ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-17" title="17">you str <span class="ot">=</span> <span class="highlight">colorPutStr <span class="dt">Yellow</span></span> (<span class="st">&quot;You: &quot;</span> <span class="op">++</span> str <span class="op">++</span> <span class="st">&quot;\n&quot;</span>)</a>
<a class="sourceLine" id="cb6-18" title="18"></a>
<a class="sourceLine" id="cb6-19" title="19"><span class="ot">intro ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-20" title="20">intro <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb6-21" title="21"> bk <span class="st">&quot;Stop!&quot;</span></a>
<a class="sourceLine" id="cb6-22" title="22"> bk <span class="st">&quot;Who would cross the Bridge of Death&quot;</span></a>
<a class="sourceLine" id="cb6-23" title="23"> bk <span class="st">&quot;must answer me these questions three,&quot;</span></a>
<a class="sourceLine" id="cb6-24" title="24"> bk <span class="st">&quot;ere the other side he see.&quot;</span></a>
<a class="sourceLine" id="cb6-25" title="25"> you <span class="st">&quot;Ask me the questions, bridgekeeper, I am not afraid.\n&quot;</span></a>
<a class="sourceLine" id="cb6-26" title="26"></a>
<a class="sourceLine" id="cb6-27" title="27"><span class="ot">end ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb6-28" title="28">end <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb6-29" title="29"> <span class="fu">putStrLn</span> <span class="st">&quot;\n\n&quot;</span></a>
<a class="sourceLine" id="cb6-30" title="30"> bk <span class="st">&quot;What... is the air-speed velocity of an unladen swallow?&quot;</span></a>
<a class="sourceLine" id="cb6-31" title="31"> you <span class="st">&quot;What do you mean? An African or European swallow?&quot;</span></a>
<a class="sourceLine" id="cb6-32" title="32"> bk <span class="st">&quot;Huh? I... I don't know that.&quot;</span></a>
<a class="sourceLine" id="cb6-33" title="33"> <span class="fu">putStrLn</span> <span class="st">&quot;[the bridgekeeper is thrown over]&quot;</span></a>
<a class="sourceLine" id="cb6-34" title="34"> bk <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb6-35" title="35"> <span class="fu">putStrLn</span> <span class="st">&quot;Sir Bedevere: How do you know so much about swallows?&quot;</span></a>
<a class="sourceLine" id="cb6-36" title="36"> you <span class="st">&quot;Well, you have to know these things when you're a king, you know.&quot;</span></a></code></pre></div>
<p>We could put this code in <code>src/Main.hs</code>. Declare a main function:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb7-1" title="1"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb7-2" title="2">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb7-3" title="3"> intro</a>
<a class="sourceLine" id="cb7-4" title="4"> end</a></code></pre></div>
<p>Make <code>cabal install</code> and run <code>cabal run</code> (or <code>./.cabal-sandbox/bin/holy-project</code>). It works!</p>
<h2 id="five-questions-three-questions-sir">Five Questions Three questions Sir!</h2>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/bring-out-your-dead.jpg" alt="Bring out your dead!" />
</div>
<p>In order to ask questions, here is how we do it in shell script:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb8-1" title="1"><span class="ex">print</span> -- <span class="st">&quot;What is your name?&quot;</span></a>
<a class="sourceLine" id="cb8-2" title="2"><span class="bu">read</span> <span class="va">name</span></a></code></pre></div>
<p>If we want to abstract things a bit, the easiest way in shell is to use a global variable<a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a> which will get the value of the user input like this:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb9-1" title="1"><span class="va">answer=</span><span class="st">&quot;&quot;</span></a>
<a class="sourceLine" id="cb9-2" title="2"><span class="fu">ask()</span><span class="kw">{</span></a>
<a class="sourceLine" id="cb9-3" title="3"> <span class="bu">local</span> <span class="va">info=</span><span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span></a>
<a class="sourceLine" id="cb9-4" title="4"> <span class="ex">bk</span> <span class="st">&quot;What is your </span><span class="va">$info</span><span class="st">?&quot;</span></a>
<a class="sourceLine" id="cb9-5" title="5"> <span class="ex">print</span> -n <span class="st">&quot;&gt; &quot;</span></a>
<a class="sourceLine" id="cb9-6" title="6"> <span class="bu">read</span> <span class="va">answer</span></a>
<a class="sourceLine" id="cb9-7" title="7"><span class="kw">}</span></a>
<a class="sourceLine" id="cb9-8" title="8"><span class="ex">...</span></a>
<a class="sourceLine" id="cb9-9" title="9"><span class="ex">ask</span> name</a>
<a class="sourceLine" id="cb9-10" title="10"><span class="va">name=</span><span class="st">&quot;</span><span class="va">$answer</span><span class="st">&quot;</span></a></code></pre></div>
<p>In Haskell we wont need any global variable:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb10-1" title="1"><span class="kw">import</span> <span class="dt">System.IO</span> (hFlush, stdout)</a>
<a class="sourceLine" id="cb10-2" title="2"><span class="op">...</span></a>
<a class="sourceLine" id="cb10-3" title="3"><span class="ot">ask ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb10-4" title="4">ask info <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb10-5" title="5"> bk <span class="op">$</span> <span class="st">&quot;What is your &quot;</span> <span class="op">++</span> info <span class="op">++</span> <span class="st">&quot;?&quot;</span></a>
<a class="sourceLine" id="cb10-6" title="6"> <span class="fu">putStr</span> <span class="st">&quot;&gt; &quot;</span></a>
<a class="sourceLine" id="cb10-7" title="7"> hFlush stdout <span class="co">-- Because we want to ask on the same line.</span></a>
<a class="sourceLine" id="cb10-8" title="8"> <span class="fu">getLine</span></a></code></pre></div>
<p>Now our main function might look like:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb11-1" title="1">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb11-2" title="2"> intro</a>
<a class="sourceLine" id="cb11-3" title="3"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span></a>
<a class="sourceLine" id="cb11-4" title="4"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;name&quot;</span></a>
<a class="sourceLine" id="cb11-5" title="5"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;email&quot;</span></a>
<a class="sourceLine" id="cb11-6" title="6"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;github account&quot;</span></a>
<a class="sourceLine" id="cb11-7" title="7"> _ <span class="ot">&lt;-</span> ask <span class="st">&quot;project in less than a dozen word&quot;</span></a>
<a class="sourceLine" id="cb11-8" title="8"> end</a></code></pre></div>
<p>You could test it with <code>cabal install</code> and then <code>./.cabal-sandbox/bin/holy-project</code>.</p>
<p>We will see later how to guess the answer using the <code>.gitconfig</code> file and the github API.</p>
<h2 id="using-answers">Using answers</h2>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/castle-of-hhhhaaaarr.jpg" alt="Castle of Aaaaarrrr????" />
</div>
<h3 id="create-the-project-name">Create the project name</h3>
<p>I dont really like the ability to use capital letter in a package name. So in shell I transform the project name like this:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb12-1" title="1"><span class="co"># replace all spaces by dashes then lowercase the string</span></a>
<a class="sourceLine" id="cb12-2" title="2"><span class="va">project=</span>${<span class="va">${project:gs</span><span class="er">/</span><span class="va"> </span><span class="er">/-/</span><span class="va">}</span>:<span class="ex">l</span>}</a></code></pre></div>
<p>In order to achieve the same result in Haskell (dont forget to add the <code>split</code> package):</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb13-1" title="1"><span class="kw">import</span> <span class="dt">Data.Char</span> (toLower)</a>
<a class="sourceLine" id="cb13-2" title="2"><span class="kw">import</span> <span class="dt">Data.List</span> (intercalate)</a>
<a class="sourceLine" id="cb13-3" title="3"><span class="kw">import</span> <span class="dt">Data.List.Split</span> (splitOneOf)</a>
<a class="sourceLine" id="cb13-4" title="4"><span class="op">...</span></a>
<a class="sourceLine" id="cb13-5" title="5"><span class="ot">projectNameFromString ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb13-6" title="6">projectNameFromString str <span class="ot">=</span> intercalate <span class="st">&quot;-&quot;</span> (splitOneOf <span class="st">&quot; -&quot;</span> (<span class="fu">map</span> <span class="fu">toLower</span> str))</a></code></pre></div>
<p>One important thing to note is that in zsh the transformation occurs on strings but in haskell we use list as intermediate representation:</p>
<pre><code>zsh:
&quot;Holy grail&quot; ==( ${project:gs/ /-/} )=&gt; &quot;Holy<span class="highlight">-</span>grail&quot;
==( ${project:l} )=&gt; &quot;<span class="highlight">h</span>oly-grail&quot;
haskell
&quot;Holy grail&quot; ==( map toLower )=&gt; &quot;<span class="highlight">h</span>oly grail&quot;
==( splitOneOf &quot; -&quot; )=&gt; <span class="highlight">[</span>&quot;holy&quot;<span class="highlight">,</span>&quot;grail&quot;<span class="highlight">]</span>
==( intercalate &quot;-&quot; )=&gt; <span class="highlight">&quot;</span>holy<span class="highlight">-</span>grail<span class="highlight">&quot;</span></code></pre>
<h3 id="create-the-module-name">Create the module name</h3>
<p>The module name is a capitalized version of the project name where we remove dashes.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb15-1" title="1"><span class="co"># Capitalize a string</span></a>
<a class="sourceLine" id="cb15-2" title="2"><span class="fu">capitalize()</span><span class="kw">{</span></a>
<a class="sourceLine" id="cb15-3" title="3"> <span class="bu">local</span> <span class="va">str=</span><span class="st">&quot;</span><span class="va">$(</span><span class="ex">print</span> -- <span class="st">&quot;</span><span class="va">$*</span><span class="st">&quot;</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s/-/ /g'</span><span class="va">)</span><span class="st">&quot;</span></a>
<a class="sourceLine" id="cb15-4" title="4"> <span class="ex">print</span> -- $<span class="dt">{(C)str}</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s/ //g'</span></a>
<a class="sourceLine" id="cb15-5" title="5"><span class="kw">}</span></a></code></pre></div>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb16-1" title="1"><span class="co">-- | transform a chain like &quot;Holy project&quot; in &quot;HolyProject&quot;</span></a>
<a class="sourceLine" id="cb16-2" title="2"><span class="ot">capitalize ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb16-3" title="3">capitalize str <span class="ot">=</span> <span class="fu">concatMap</span> capitalizeWord (splitOneOf <span class="st">&quot; -&quot;</span> str)</a>
<a class="sourceLine" id="cb16-4" title="4"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb16-5" title="5"><span class="ot"> capitalizeWord ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb16-6" title="6"> capitalizeWord (x<span class="op">:</span>xs) <span class="ot">=</span> <span class="fu">toUpper</span> x<span class="op">:</span><span class="fu">map</span> <span class="fu">toLower</span> xs</a>
<a class="sourceLine" id="cb16-7" title="7"> capitalizeWord _ <span class="ot">=</span> []</a></code></pre></div>
<p>The haskell version is made by hand where zsh already had a capitalize operation on string with many words. Here is the difference between the shell and haskell way (note I splitted the effect of <code>concatMap</code> as <code>map</code> and <code>concat</code>):</p>
<pre><code>shell:
&quot;Holy-grail&quot; ==( sed 's/-/ /g' )=&gt; &quot;Holy<span class="highlight"> </span>grail&quot;
==( ${(C)str} )=&gt; &quot;Holy <span class="highlight">G</span>rail&quot;
==( sed 's/ //g' )=&gt; &quot;HolyGrail&quot;
haskell:
&quot;Holy-grail&quot; ==( splitOneOf &quot; -&quot; )=&gt; <span class="highlight">[</span>&quot;Holy&quot;<span class="highlight">,</span>&quot;grail&quot;<span class="highlight">]</span>
==( map capitalizeWord )=&gt; [&quot;Holy&quot;,&quot;<span class="highlight">G</span>rail&quot;]
==( concat )=&gt; &quot;HolyGrail&quot;</code></pre>
<p>As the preceding example, in shell we work on strings while Haskell use temporary lists representations.</p>
<h3 id="check-the-project-name">Check the project name</h3>
<p>Also I want to be quite restrictive on the kind of project name we can give. This is why I added a check function.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb18-1" title="1"><span class="ot">ioassert ::</span> <span class="dt">Bool</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb18-2" title="2">ioassert <span class="dt">True</span> _ <span class="ot">=</span> <span class="fu">return</span> ()</a>
<a class="sourceLine" id="cb18-3" title="3">ioassert <span class="dt">False</span> str <span class="ot">=</span> <span class="fu">error</span> str</a>
<a class="sourceLine" id="cb18-4" title="4"></a>
<a class="sourceLine" id="cb18-5" title="5"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb18-6" title="6">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb18-7" title="7"> intro</a>
<a class="sourceLine" id="cb18-8" title="8"> project <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span></a>
<a class="sourceLine" id="cb18-9" title="9"> ioassert (checkProjectName project)</a>
<a class="sourceLine" id="cb18-10" title="10"> <span class="st">&quot;Use only letters, numbers, spaces and dashes please&quot;</span></a>
<a class="sourceLine" id="cb18-11" title="11"> <span class="kw">let</span> projectname <span class="ot">=</span> projectNameFromString project</a>
<a class="sourceLine" id="cb18-12" title="12"> modulename <span class="ot">=</span> capitalize project</a></code></pre></div>
<p>Which verify the project name is not empty and use only letter, numbers and dashes:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb19-1" title="1"><span class="co">-- | verify if project name is conform</span></a>
<a class="sourceLine" id="cb19-2" title="2"><span class="ot">checkProjectName ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Bool</span></a>
<a class="sourceLine" id="cb19-3" title="3">checkProjectName [] <span class="ot">=</span> <span class="dt">False</span></a>
<a class="sourceLine" id="cb19-4" title="4">checkProjectName str <span class="ot">=</span></a>
<a class="sourceLine" id="cb19-5" title="5"> <span class="fu">all</span> (\c <span class="ot">-&gt;</span> isLetter c <span class="op">||</span> isNumber c <span class="op">||</span> c<span class="op">==</span><span class="ch">'-'</span> <span class="op">||</span> c<span class="op">==</span><span class="ch">' '</span>) str</a></code></pre></div>
<h2 id="create-the-project">Create the project</h2>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/giant-three-head.jpg" alt="Giant with three heads and mustaches" />
</div>
<p>Making a project will consists in creating files and directories whose name and content depends on the answer we had until now.</p>
<p>In shell, for each file to create, we used something like:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb20-1" title="1"><span class="op">&gt;</span> <span class="ex">file-to-create</span> cat <span class="op">&lt;&lt;END</span></a>
<a class="sourceLine" id="cb20-2" title="2">file content here.</a>
<a class="sourceLine" id="cb20-3" title="3">We can use <span class="va">$variables</span> here</a>
<a class="sourceLine" id="cb20-4" title="4"><span class="op">END</span></a></code></pre></div>
<p>In Haskell, while possible, we shouldnt put the file content in the source code. We have a relatively easy way to include external file in a cabal package. This is what we will be using.</p>
<p>Furthermore, we need a templating system to replace small part of the static file by computed values. For this task, I choose to use <a href="http://hackage.haskell.org/package/hastache"><code>hastache</code></a>, a Haskell implementation of Mustache templates<a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a>.</p>
<h3 id="add-external-files-in-a-cabal-project">Add external files in a cabal project</h3>
<p>Cabal provides a way to add files which are not source files to a package. You simply have to add a <code>Data-Files:</code> entry in the header of the cabal file:</p>
<pre><code>data-files: scaffold/LICENSE
, scaffold/Setup.hs
, scaffold/auto-update
, scaffold/gitignore
, scaffold/interact
, scaffold/project.cabal
, scaffold/src/Main.hs
, scaffold/src/ModuleName.hs
, scaffold/src/ModuleName/Coconut.hs
, scaffold/src/ModuleName/Swallow.hs
, scaffold/test/ModuleName/Coconut/Test.hs
, scaffold/test/ModuleName/Swallow/Test.hs
, scaffold/test/Test.hs</code></pre>
<p>Now we simply have to create our files at the specified path. Here is for example the first lines of the LICENSE file.</p>
<pre class="mustache"><code>The MIT License (MIT)
Copyright (c) <span class="highlight">{{year}}</span> <span class="highlight">{{author}}</span>
Permission is hereby granted, free of charge, to any person obtaining a copy
...</code></pre>
<p>It will be up to our program to replace the <code>{{year}}</code> and <code>{{author}}</code> at runtime. We have to find the files. Cabal will create a module named <code>Paths_holy_project</code>. If we import this module we have the function <code>genDataFileName</code> at our disposal. Now we can read the files at runtime like this:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb23-1" title="1"> <span class="op">...</span></a>
<a class="sourceLine" id="cb23-2" title="2"> <span class="kw">do</span></a>
<a class="sourceLine" id="cb23-3" title="3"> pkgFilePath <span class="ot">&lt;-</span> <span class="highlight">getDataFileName <span class="st">&quot;scaffold/LICENSE&quot;</span></span></a>
<a class="sourceLine" id="cb23-4" title="4"> templateContent <span class="ot">&lt;-</span> <span class="fu">readFile</span> pkgFilePath</a>
<a class="sourceLine" id="cb23-5" title="5"> <span class="op">...</span></a></code></pre></div>
<h3 id="create-files-and-directories">Create files and directories</h3>
<p>A first remark is for portability purpose we shouldnt use String for file path. For example on Windows <code>/</code> isnt considered as a subdirectory character. To resolve this problem we will use <code>FilePath</code>:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb24-1" title="1"><span class="kw">import</span> <span class="dt">System.Directory</span></a>
<a class="sourceLine" id="cb24-2" title="2"><span class="kw">import</span> <span class="dt">System.FilePath.Posix</span> (takeDirectory,(&lt;/&gt;))</a>
<a class="sourceLine" id="cb24-3" title="3"><span class="op">...</span></a>
<a class="sourceLine" id="cb24-4" title="4">createProject <span class="op">...</span> <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb24-5" title="5"> <span class="op">...</span></a>
<a class="sourceLine" id="cb24-6" title="6"> <span class="highlight">createDirectory</span> projectName <span class="co">-- mkdir</span></a>
<a class="sourceLine" id="cb24-7" title="7"> <span class="highlight">setCurrentDirectory</span> projectName <span class="co">-- cd</span></a>
<a class="sourceLine" id="cb24-8" title="8"> genFile <span class="st">&quot;LICENSE&quot;</span> <span class="st">&quot;LICENSE&quot;</span></a>
<a class="sourceLine" id="cb24-9" title="9"> genFile <span class="st">&quot;gitignore&quot;</span> <span class="st">&quot;.gitignore&quot;</span></a>
<a class="sourceLine" id="cb24-10" title="10"> genFile <span class="st">&quot;src/Main.hs&quot;</span> (<span class="st">&quot;src&quot;</span> <span class="op">&lt;/&gt;</span> <span class="st">&quot;Main.hs&quot;</span>)</a>
<a class="sourceLine" id="cb24-11" title="11"></a>
<a class="sourceLine" id="cb24-12" title="12">genFile dataFilename outputFilename <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb24-13" title="13"> pkgfileName <span class="ot">&lt;-</span> getDataFileName (<span class="st">&quot;scaffold/&quot;</span> <span class="op">++</span> filename)</a>
<a class="sourceLine" id="cb24-14" title="14"> template <span class="ot">&lt;-</span> <span class="fu">readFile</span> pkgfileName</a>
<a class="sourceLine" id="cb24-15" title="15"> transformedFile <span class="ot">&lt;-</span> <span class="op">???</span> <span class="co">-- hastache magic here</span></a>
<a class="sourceLine" id="cb24-16" title="16"> <span class="highlight">createDirectoryIfMissing</span> <span class="dt">True</span> (takeDirectory outputFileName)</a>
<a class="sourceLine" id="cb24-17" title="17"> <span class="highlight"><span class="fu">writeFile</span></span> outputFileName transformedFile</a></code></pre></div>
<h3 id="use-hastache">Use Hastache</h3>
<p>In order to use hastache we can either create a context manually or use generics to create a context from a record. This is the last option we will show here. So in a first time, we need to import some modules and declare a record containing all necessary informations to create our project.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb25-1" title="1"><span class="ot">{-# LANGUAGE DeriveDataTypeable #-}</span></a>
<a class="sourceLine" id="cb25-2" title="2"><span class="op">...</span></a>
<a class="sourceLine" id="cb25-3" title="3"><span class="kw">import</span> <span class="dt">Data.Data</span></a>
<a class="sourceLine" id="cb25-4" title="4"><span class="kw">import</span> <span class="dt">Text.Hastache</span></a>
<a class="sourceLine" id="cb25-5" title="5"><span class="kw">import</span> <span class="dt">Text.Hastache.Context</span></a>
<a class="sourceLine" id="cb25-6" title="6"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString</span> <span class="kw">as</span> <span class="dt">BS</span></a>
<a class="sourceLine" id="cb25-7" title="7"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.ByteString.Lazy.Char8</span> <span class="kw">as</span> <span class="dt">LZ</span></a></code></pre></div>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb26-1" title="1"><span class="kw">data</span> <span class="dt">Project</span> <span class="ot">=</span> <span class="dt">Project</span> {</a>
<a class="sourceLine" id="cb26-2" title="2"><span class="ot"> projectName ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-3" title="3"> ,<span class="ot"> moduleName ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-4" title="4"> ,<span class="ot"> author ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-5" title="5"> ,<span class="ot"> mail ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-6" title="6"> ,<span class="ot"> ghaccount ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-7" title="7"> ,<span class="ot"> synopsis ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-8" title="8"> ,<span class="ot"> year ::</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb26-9" title="9"> } <span class="kw">deriving</span> (<span class="dt">Data</span>, <span class="dt">Typeable</span>)</a></code></pre></div>
<p>Once we have declared this, we should populate our Project record with the data provided by the user. So our main function should look like:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb27-1" title="1"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb27-2" title="2">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb27-3" title="3"> intro</a>
<a class="sourceLine" id="cb27-4" title="4"> project <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span></a>
<a class="sourceLine" id="cb27-5" title="5"> ioassert (checkProjectName project)</a>
<a class="sourceLine" id="cb27-6" title="6"> <span class="st">&quot;Use only letters, numbers, spaces and dashes please&quot;</span></a>
<a class="sourceLine" id="cb27-7" title="7"> <span class="kw">let</span> projectname <span class="ot">=</span> projectNameFromString project</a>
<a class="sourceLine" id="cb27-8" title="8"> modulename <span class="ot">=</span> capitalize project</a>
<a class="sourceLine" id="cb27-9" title="9"> <span class="highlight">in_author</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;name&quot;</span></a>
<a class="sourceLine" id="cb27-10" title="10"> <span class="highlight">in_email</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;email&quot;</span></a>
<a class="sourceLine" id="cb27-11" title="11"> <span class="highlight">in_ghaccount</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;github account&quot;</span></a>
<a class="sourceLine" id="cb27-12" title="12"> <span class="highlight">in_synopsis</span> <span class="ot">&lt;-</span> ask <span class="st">&quot;project in less than a dozen word?&quot;</span></a>
<a class="sourceLine" id="cb27-13" title="13"> <span class="highlight">current_year</span> <span class="ot">&lt;-</span> getCurrentYear</a>
<a class="sourceLine" id="cb27-14" title="14"> createProject <span class="op">$</span> <span class="highlight"><span class="dt">Project</span> projectname modulename in_author in_email</span></a>
<a class="sourceLine" id="cb27-15" title="15"> <span class="highlight">in_ghaccount in_synopsis current_year</span></a>
<a class="sourceLine" id="cb27-16" title="16"> end</a></code></pre></div>
<p>Finally we could use hastache this way:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb28-1" title="1"><span class="ot">createProject ::</span> <span class="highlight"><span class="dt">Project</span></span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb28-2" title="2">createProject <span class="highlight">p</span> <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb28-3" title="3"> <span class="kw">let</span> <span class="highlight">context</span> <span class="ot">=</span> <span class="highlight">mkGenericContext p</span></a>
<a class="sourceLine" id="cb28-4" title="4"> createDirectory (<span class="highlight">projectName p</span>)</a>
<a class="sourceLine" id="cb28-5" title="5"> setCurrentDirectory (<span class="highlight">projectName p</span>)</a>
<a class="sourceLine" id="cb28-6" title="6"> genFile <span class="highlight">context</span> <span class="st">&quot;gitignore&quot;</span> <span class="op">$</span> <span class="st">&quot;.gitignore&quot;</span></a>
<a class="sourceLine" id="cb28-7" title="7"> genFile <span class="highlight">context</span> <span class="st">&quot;project.cabal&quot;</span> <span class="op">$</span> (projectName p) <span class="op">++</span> <span class="st">&quot;.cabal&quot;</span></a>
<a class="sourceLine" id="cb28-8" title="8"> genFile <span class="highlight">context</span> <span class="st">&quot;src/Main.hs&quot;</span>) <span class="op">$</span> <span class="st">&quot;src&quot;</span> <span class="op">&lt;/&gt;</span> <span class="st">&quot;Main.hs&quot;</span></a>
<a class="sourceLine" id="cb28-9" title="9"> <span class="op">...</span></a>
<a class="sourceLine" id="cb28-10" title="10"></a>
<a class="sourceLine" id="cb28-11" title="11"><span class="ot">genFile ::</span> <span class="dt">MuContext</span> <span class="dt">IO</span> <span class="ot">-&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> <span class="dt">FilePath</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb28-12" title="12">genFile context filename outputFileName <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb28-13" title="13"> pkgfileName <span class="ot">&lt;-</span> getDataFileName (<span class="st">&quot;scaffold/&quot;</span><span class="op">++</span>filename)</a>
<a class="sourceLine" id="cb28-14" title="14"> template <span class="ot">&lt;-</span> <span class="highlight"><span class="dt">BS</span><span class="op">.</span></span><span class="fu">readFile</span> pkgfileName</a>
<a class="sourceLine" id="cb28-15" title="15"> transformedFile <span class="ot">&lt;-</span> <span class="highlight">hastacheStr defaultConfig template context</span></a>
<a class="sourceLine" id="cb28-16" title="16"> createDirectoryIfMissing <span class="dt">True</span> (takeDirectory outputFileName)</a>
<a class="sourceLine" id="cb28-17" title="17"> <span class="highlight"><span class="dt">LZ</span><span class="op">.</span></span><span class="fu">writeFile</span> outputFileName transformedFile</a></code></pre></div>
<p>We use external files in mustache format. We ask question to our user to fill a data structure. We use this data structure to create a context. Hastache use this context with the external files to create the project files.</p>
<h2 id="git-and-cabal">Git and Cabal</h2>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/tim.jpg" alt="Tim" />
</div>
<p>We need to initialize git and cabal. For this we simply call external command with the <code>system</code> function.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb29-1" title="1"><span class="kw">import</span> <span class="dt">System.Cmd</span></a>
<a class="sourceLine" id="cb29-2" title="2"></a>
<a class="sourceLine" id="cb29-3" title="3"><span class="op">...</span></a>
<a class="sourceLine" id="cb29-4" title="4">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb29-5" title="5"> <span class="op">...</span></a>
<a class="sourceLine" id="cb29-6" title="6"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;git init .&quot;</span></a>
<a class="sourceLine" id="cb29-7" title="7"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;cabal sandbox init&quot;</span></a>
<a class="sourceLine" id="cb29-8" title="8"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;cabal install&quot;</span></a>
<a class="sourceLine" id="cb29-9" title="9"> _ <span class="ot">&lt;-</span> system <span class="st">&quot;cabal test&quot;</span></a>
<a class="sourceLine" id="cb29-10" title="10"> _ <span class="ot">&lt;-</span> system <span class="op">$</span> <span class="st">&quot;./.cabal-sandbox/bin/test-&quot;</span> <span class="op">++</span> projectName</a></code></pre></div>
<h2 id="ameliorations">Ameliorations</h2>
<p>Our job is almost finished. Now, we only need to add some nice feature to make the application more enjoyable.</p>
<h3 id="better-error-message">Better error message</h3>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/rabbit.jpg" alt="Rabbit" />
</div>
<p>The first one would be to add a better error message.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb30-1" title="1"><span class="kw">import</span> <span class="dt">System.Random</span></a>
<a class="sourceLine" id="cb30-2" title="2"></a>
<a class="sourceLine" id="cb30-3" title="3"><span class="ot">holyError ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb30-4" title="4">holyError str <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb30-5" title="5"> r <span class="ot">&lt;-</span> randomIO</a>
<a class="sourceLine" id="cb30-6" title="6"> <span class="kw">if</span> r</a>
<a class="sourceLine" id="cb30-7" title="7"> <span class="kw">then</span></a>
<a class="sourceLine" id="cb30-8" title="8"> <span class="kw">do</span></a>
<a class="sourceLine" id="cb30-9" title="9"> bk <span class="st">&quot;What... is your favourite colour?&quot;</span></a>
<a class="sourceLine" id="cb30-10" title="10"> you <span class="st">&quot;Blue. No, yel...&quot;</span></a>
<a class="sourceLine" id="cb30-11" title="11"> <span class="fu">putStrLn</span> <span class="st">&quot;[You are thrown over the edge into the volcano]&quot;</span></a>
<a class="sourceLine" id="cb30-12" title="12"> you <span class="st">&quot;You: Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb30-13" title="13"> bk <span class="st">&quot; Hee hee heh.&quot;</span></a>
<a class="sourceLine" id="cb30-14" title="14"> <span class="kw">else</span></a>
<a class="sourceLine" id="cb30-15" title="15"> <span class="kw">do</span></a>
<a class="sourceLine" id="cb30-16" title="16"> bk <span class="st">&quot;What is the capital of Assyria?&quot;</span></a>
<a class="sourceLine" id="cb30-17" title="17"> you <span class="st">&quot;I don't know that!&quot;</span></a>
<a class="sourceLine" id="cb30-18" title="18"> <span class="fu">putStrLn</span> <span class="st">&quot;[You are thrown over the edge into the volcano]&quot;</span></a>
<a class="sourceLine" id="cb30-19" title="19"> you <span class="st">&quot;Auuuuuuuuuuuugh&quot;</span></a>
<a class="sourceLine" id="cb30-20" title="20"> <span class="fu">error</span> (<span class="ch">'\n'</span><span class="op">:</span>str)</a></code></pre></div>
<p>And also update where this can be called</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb31-1" title="1"><span class="ot">ioassert ::</span> <span class="dt">Bool</span> <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb31-2" title="2">ioassert <span class="dt">True</span> _ <span class="ot">=</span> <span class="fu">return</span> ()</a>
<a class="sourceLine" id="cb31-3" title="3">ioassert <span class="dt">False</span> str <span class="ot">=</span> holyError str</a></code></pre></div>
<h3 id="use-.gitconfig">Use <code>.gitconfig</code></h3>
<p>We want to retrieve the <code>~/.gitconfig</code> file content and see if it contains a name and email information. We will need to access to the <code>HOME</code> environment variable. Also, as we use bytestring package for hastache, lets take advantage of this library.</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb32-1" title="1"><span class="kw">import</span> <span class="dt">Data.Maybe</span> (fromJust)</a>
<a class="sourceLine" id="cb32-2" title="2"><span class="kw">import</span> <span class="dt">System.Environment</span> (getEnv)</a>
<a class="sourceLine" id="cb32-3" title="3"><span class="kw">import</span> <span class="dt">Control.Exception</span></a>
<a class="sourceLine" id="cb32-4" title="4"><span class="kw">import</span> <span class="dt">System.IO.Error</span></a>
<a class="sourceLine" id="cb32-5" title="5"><span class="kw">import</span> <span class="dt">Control.Monad</span> (guard)</a>
<a class="sourceLine" id="cb32-6" title="6"></a>
<a class="sourceLine" id="cb32-7" title="7"><span class="ot">safeReadGitConfig ::</span> <span class="dt">IO</span> <span class="dt">LZ.ByteString</span></a>
<a class="sourceLine" id="cb32-8" title="8">safeReadGitConfig <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb32-9" title="9"> e <span class="ot">&lt;-</span> tryJust (guard <span class="op">.</span> isDoesNotExistError)</a>
<a class="sourceLine" id="cb32-10" title="10"> (<span class="kw">do</span></a>
<a class="sourceLine" id="cb32-11" title="11"> home <span class="ot">&lt;-</span> getEnv <span class="st">&quot;HOME&quot;</span></a>
<a class="sourceLine" id="cb32-12" title="12"> LZ.readFile <span class="op">$</span> home <span class="op">++</span> <span class="st">&quot;/.gitconfig&quot;</span> )</a>
<a class="sourceLine" id="cb32-13" title="13"> <span class="fu">return</span> <span class="op">$</span> <span class="fu">either</span> (<span class="fu">const</span> (LZ.empty)) <span class="fu">id</span> e</a>
<a class="sourceLine" id="cb32-14" title="14"><span class="op">...</span></a>
<a class="sourceLine" id="cb32-15" title="15">main <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb32-16" title="16"> gitconfig <span class="ot">&lt;-</span> safeReadGitConfig</a>
<a class="sourceLine" id="cb32-17" title="17"> <span class="kw">let</span> (name,email) <span class="ot">=</span> <span class="highlight">getNameAndMail</span> gitconfig</a>
<a class="sourceLine" id="cb32-18" title="18"> project <span class="ot">&lt;-</span> ask <span class="st">&quot;project name&quot;</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb32-19" title="19"> <span class="op">...</span></a>
<a class="sourceLine" id="cb32-20" title="20"> in_author <span class="ot">&lt;-</span> ask <span class="st">&quot;name&quot;</span> name</a>
<a class="sourceLine" id="cb32-21" title="21"> <span class="op">...</span></a></code></pre></div>
<p>We could note I changed the ask function slightly to take a maybe parameter.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb33-1" title="1"><span class="ot">ask ::</span> <span class="dt">String</span> <span class="highlight"><span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span></span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb33-2" title="2">ask info hint <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb33-3" title="3"> bk <span class="op">$</span> <span class="st">&quot;What is your &quot;</span> <span class="op">++</span> info <span class="op">++</span> <span class="st">&quot;?&quot;</span> <span class="op">++</span> <span class="highlight">(<span class="fu">maybe</span> <span class="st">&quot;&quot;</span> (\h <span class="ot">-&gt;</span> <span class="st">&quot; (&quot;</span><span class="op">++</span>h<span class="op">++</span><span class="st">&quot;)&quot;</span>) hint)</span></a>
<a class="sourceLine" id="cb33-4" title="4"> <span class="op">...</span></a></code></pre></div>
<p>Concerning the parsing of <code>.gitconfig</code>, it is quite minimalist.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb34-1" title="1"><span class="ot">getNameAndMail ::</span> <span class="dt">LZ.ByteString</span> <span class="ot">-&gt;</span> (<span class="dt">Maybe</span> <span class="dt">String</span>,<span class="dt">Maybe</span> <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb34-2" title="2">getNameAndMail gitConfigContent <span class="ot">=</span> (getFirstValueFor splitted <span class="st">&quot;name&quot;</span>,</a>
<a class="sourceLine" id="cb34-3" title="3"> getFirstValueFor splitted <span class="st">&quot;email&quot;</span>)</a>
<a class="sourceLine" id="cb34-4" title="4"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb34-5" title="5"> <span class="co">-- make lines of words</span></a>
<a class="sourceLine" id="cb34-6" title="6"><span class="ot"> splitted ::</span> [[<span class="dt">LZ.ByteString</span>]]</a>
<a class="sourceLine" id="cb34-7" title="7"> splitted <span class="ot">=</span> <span class="fu">map</span> LZ.words (LZ.lines gitConfigContent)</a>
<a class="sourceLine" id="cb34-8" title="8"></a>
<a class="sourceLine" id="cb34-9" title="9"><span class="co">-- Get the first line which start with</span></a>
<a class="sourceLine" id="cb34-10" title="10"><span class="co">-- 'elem =' and return the third field (value)</span></a>
<a class="sourceLine" id="cb34-11" title="11"><span class="ot">getFirstValueFor ::</span> [[<span class="dt">LZ.ByteString</span>]] <span class="ot">-&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span></a>
<a class="sourceLine" id="cb34-12" title="12">getFirstValueFor splitted key <span class="ot">=</span> firstJust (<span class="fu">map</span> (getValueForKey key) splitted)</a>
<a class="sourceLine" id="cb34-13" title="13"></a>
<a class="sourceLine" id="cb34-14" title="14"><span class="co">-- return the first Just value of a list of Maybe</span></a>
<a class="sourceLine" id="cb34-15" title="15"><span class="ot">firstJust ::</span> (<span class="dt">Eq</span> a) <span class="ot">=&gt;</span> [<span class="dt">Maybe</span> a] <span class="ot">-&gt;</span> <span class="dt">Maybe</span> a</a>
<a class="sourceLine" id="cb34-16" title="16">firstJust l <span class="ot">=</span> <span class="kw">case</span> <span class="fu">dropWhile</span> (<span class="op">==</span><span class="dt">Nothing</span>) l <span class="kw">of</span></a>
<a class="sourceLine" id="cb34-17" title="17"> [] <span class="ot">-&gt;</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb34-18" title="18"> (j<span class="op">:</span>_) <span class="ot">-&gt;</span> j</a>
<a class="sourceLine" id="cb34-19" title="19"></a>
<a class="sourceLine" id="cb34-20" title="20"><span class="co">-- Given a line of words (&quot;word1&quot;:&quot;word2&quot;:rest)</span></a>
<a class="sourceLine" id="cb34-21" title="21"><span class="co">-- getValue will return rest if word1 == key</span></a>
<a class="sourceLine" id="cb34-22" title="22"><span class="co">-- 'elem =' or Nothing otherwise</span></a>
<a class="sourceLine" id="cb34-23" title="23"><span class="ot">getValueForKey ::</span> <span class="dt">String</span> <span class="co">-- key</span></a>
<a class="sourceLine" id="cb34-24" title="24"> <span class="ot">-&gt;</span> [<span class="dt">LZ.ByteString</span>] <span class="co">-- line of words</span></a>
<a class="sourceLine" id="cb34-25" title="25"> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">String</span> <span class="co">-- the value if found</span></a>
<a class="sourceLine" id="cb34-26" title="26">getValueForKey el (n<span class="op">:</span>e<span class="op">:</span>xs) <span class="ot">=</span> <span class="kw">if</span> (n <span class="op">==</span> (LZ.pack el)) <span class="op">&amp;&amp;</span> (e <span class="op">==</span> (LZ.pack <span class="st">&quot;=&quot;</span>))</a>
<a class="sourceLine" id="cb34-27" title="27"> <span class="kw">then</span> <span class="dt">Just</span> (LZ.unpack (LZ.unwords xs))</a>
<a class="sourceLine" id="cb34-28" title="28"> <span class="kw">else</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb34-29" title="29">getValueForKey _ _ <span class="ot">=</span> <span class="dt">Nothing</span></a></code></pre></div>
<p>We could notice, <code>getNameAndMail</code> doesnt read the full file and stop at the first occurrence of name and mail.</p>
<h3 id="use-the-github-api">Use the github API</h3>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/coconut.jpg" alt="Coconut and Swallow" />
</div>
<p>The task seems relatively easy, but well see there will be some complexity hidden. Make a request on <code>https://api.github.com/search/users?q=&lt;email&gt;</code>. Parse the JSON and get the <code>login</code> field of the first item.</p>
<p>So the first problem to handle is to connect an URL. For this we will use the <code>http-conduit</code> package.</p>
<p>Generally, for simple request, we should use:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb35-1" title="1"><span class="kw">do</span></a>
<a class="sourceLine" id="cb35-2" title="2"> body <span class="ot">&lt;-</span> simpleHTTP (<span class="st">&quot;https://api.github.com/search/users?q=&quot;</span> <span class="op">++</span> email)</a>
<a class="sourceLine" id="cb35-3" title="3"> <span class="op">...</span></a></code></pre></div>
<p>But, after some research, I discovered we must declare an User-Agent in the HTTP header to be accepted by the github API. So we have to change the HTTP Header, and our code became slightly more complex:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb36-1" title="1"><span class="ot">{-# LANGUAGE OverloadedStrings #-}</span></a>
<a class="sourceLine" id="cb36-2" title="2"><span class="op">...</span></a>
<a class="sourceLine" id="cb36-3" title="3"><span class="ot">simpleHTTPWithUserAgent ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> <span class="dt">LZ.ByteString</span></a>
<a class="sourceLine" id="cb36-4" title="4">simpleHTTPWithUserAgent url <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb36-5" title="5"> r <span class="ot">&lt;-</span> parseUrl url</a>
<a class="sourceLine" id="cb36-6" title="6"> <span class="kw">let</span> request <span class="ot">=</span> r { requestHeaders <span class="ot">=</span> [ (<span class="st">&quot;User-Agent&quot;</span>,<span class="st">&quot;HTTP-Conduit&quot;</span>) ] }</a>
<a class="sourceLine" id="cb36-7" title="7"> withManager <span class="op">$</span> (<span class="fu">return</span><span class="op">.</span>responseBody) <span class="op">&lt;=&lt;</span> httpLbs request</a>
<a class="sourceLine" id="cb36-8" title="8"></a>
<a class="sourceLine" id="cb36-9" title="9"><span class="ot">getGHUser ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Maybe</span> <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb36-10" title="10">getGHUser <span class="st">&quot;&quot;</span> <span class="ot">=</span> <span class="fu">return</span> <span class="dt">Nothing</span></a>
<a class="sourceLine" id="cb36-11" title="11">getGHUser email <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb36-12" title="12"> <span class="kw">let</span> url <span class="ot">=</span> <span class="st">&quot;https://api.github.com/search/users?q=&quot;</span> <span class="op">++</span> email</a>
<a class="sourceLine" id="cb36-13" title="13"> body <span class="ot">&lt;-</span> simpleHTTPWithUserAgent url</a>
<a class="sourceLine" id="cb36-14" title="14"> <span class="op">...</span></a></code></pre></div>
<p>So now, we have a String containing a JSON representation. In javascript we would have used <code>login=JSON.parse(body).items[0].login</code>. How does Haskell will handle it (knowing the J in JSON is for Javascript)?</p>
<p>First we will need to add the <code>lens-aeson</code> package and use it that way:</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb37-1" title="1"><span class="kw">import</span> <span class="dt">Control.Lens.Operators</span> ((^?))</a>
<a class="sourceLine" id="cb37-2" title="2"><span class="kw">import</span> <span class="dt">Control.Lens.Aeson</span></a>
<a class="sourceLine" id="cb37-3" title="3"><span class="kw">import</span> <span class="dt">Data.Aeson.Encode</span> (fromValue)</a>
<a class="sourceLine" id="cb37-4" title="4"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text.Lazy</span> <span class="kw">as</span> <span class="dt">TLZ</span></a>
<a class="sourceLine" id="cb37-5" title="5"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Data.Text.Lazy.Builder</span> <span class="kw">as</span> <span class="dt">TLB</span></a>
<a class="sourceLine" id="cb37-6" title="6"></a>
<a class="sourceLine" id="cb37-7" title="7"><span class="ot">getGHUser ::</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">IO</span> (<span class="dt">Maybe</span> <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb37-8" title="8">getGHUser email <span class="ot">=</span> <span class="kw">do</span></a>
<a class="sourceLine" id="cb37-9" title="9"> <span class="kw">let</span> url <span class="ot">=</span> <span class="st">&quot;https://api.github.com/search/users?q=&quot;</span> <span class="op">++</span> email</a>
<a class="sourceLine" id="cb37-10" title="10"> body <span class="ot">&lt;-</span> simpleHTTPWithUserAgent url</a>
<a class="sourceLine" id="cb37-11" title="11"> <span class="kw">let</span> login <span class="ot">=</span> <span class="highlight">body <span class="op">^?</span> key <span class="st">&quot;items&quot;</span> <span class="op">.</span> nth <span class="dv">0</span> <span class="op">.</span> key <span class="st">&quot;login&quot;</span></span></a>
<a class="sourceLine" id="cb37-12" title="12"> <span class="fu">return</span> <span class="op">$</span> <span class="fu">fmap</span> jsonValueToString login</a>
<a class="sourceLine" id="cb37-13" title="13"> <span class="kw">where</span></a>
<a class="sourceLine" id="cb37-14" title="14"> jsonValueToString <span class="ot">=</span> TLZ.unpack <span class="op">.</span> TLB.toLazyText <span class="op">.</span> fromValue</a></code></pre></div>
<p>It looks ugly, but its terse. In fact each function <code>(^?)</code>, <code>key</code> and <code>nth</code> has some great mathematical properties and everything is type safe. Unfortunately I had to make my own <code>jsonValueToString</code>. I hope I simply missed a simpler existing function.</p>
<p>You can read <a href="https://www.fpcomplete.com/user/tel/lens-aeson-traversals-prisms">this article on <code>lens-aeson</code> and prisms</a> to know more.</p>
<h4 id="concurrency">Concurrency</h4>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/priest.jpg" alt="Priests" />
</div>
<p>We now have all the feature provided by the original <code>zsh</code> script shell. But here is a good occasion to use some Haskell great feature.</p>
<p>We will launch the API request sooner and in parallel to minimize our wait time:</p>
<pre><code>import Control.Concurrent
...
main :: IO ()
main = do
intro
gitconfig &lt;- safeReadGitConfig
let (name,email) = getNameAndMail gitconfig
<span class="highlight">earlyhint &lt;- newEmptyMVar</span>
<span class="highlight">maybe (putMVar earlyhint Nothing)</span> -- if no email found put Nothing
<span class="highlight">(\hintmail -&gt; do</span> -- in the other case request the github API
<span class="highlight">forkIO (putMVar earlyhint =&lt;&lt; getGHUser hintmail)</span>
<span class="highlight">return ())</span>
<span class="highlight">email</span>
project &lt;- ask &quot;project name&quot; Nothing
ioassert (checkProjectName project)
&quot;Use only letters, numbers, spaces and dashes please&quot;
let projectname = projectNameFromString project
modulename = capitalize project
in_author &lt;- ask &quot;name&quot; name
in_email &lt;- ask &quot;email&quot; email
<span class="highlight">ghUserHint &lt;- if maybe &quot;&quot; id email /= in_email</span>
<span class="highlight">then getGHUser in_email</span>
<span class="highlight">else takeMVar earlyhint</span>
in_ghaccount &lt;- ask &quot;github account&quot; ghUserHint
in_synopsis &lt;- ask &quot;project in less than a dozen word?&quot; Nothing
current_year &lt;- getCurrentYear
createProject $ Project projectname modulename in_author in_email
in_ghaccount in_synopsis current_year
end</code></pre>
<p>While it might feel a bit confusing, it is in fact quite simple.</p>
<ol type="1">
<li>declare an <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent-MVar.html"><code>MVar</code></a>. Mainly a variable which either is empty or contains something.</li>
<li>If we didnt found any email hint, put Nothing in the <code>MVar</code>.</li>
<li>If we have an email hint, ask on the github API in a new process and once finished put the result in the <code>MVar</code>.</li>
<li>If the user enter an email different from the hint email, then just request the github api now.</li>
<li>If the user enter the same email, then wait for the MVar to be filled and ask the next question with the result.</li>
</ol>
<p>If you have a github account and had set correctly your <code>.gitconfig</code>, you might not even wait.</p>
<h2 id="project-structure">Project Structure</h2>
<p>We have a working product. But, I dont consider our job finished. The code is about 335 lines.</p>
<p>Considering that we:</p>
<ul>
<li>have 29 lines of import and 52 lines of comments (rest 255 lines)</li>
<li>ask questions</li>
<li>use a templating system to generate files</li>
<li>call an asynchronous HTTP request</li>
<li>parse JSON</li>
<li>parse <code>.gitconfig</code></li>
<li>use colored output</li>
</ul>
<p>This is quite few.</p>
<h3 id="modularizing">Modularizing</h3>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/black-knight.jpg" alt="The Black Knight" />
</div>
<p>For short programs it is not obvious to split them into different modules. But my personal preference is to split it anyway.</p>
<p>First we put all content of <code>src/Main.hs</code> in <code>src/HolyProject.hs</code>. We rename the <code>main</code> function by <code>holyStarter</code>. And our <code>src/Main.hs</code> should contains:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb39-1" title="1"><span class="kw">module</span> <span class="dt">Main</span> <span class="kw">where</span></a>
<a class="sourceLine" id="cb39-2" title="2"><span class="kw">import</span> <span class="dt">HolyProject</span></a>
<a class="sourceLine" id="cb39-3" title="3"><span class="ot">main ::</span> <span class="dt">IO</span> ()</a>
<a class="sourceLine" id="cb39-4" title="4">main <span class="ot">=</span> holyStarter</a></code></pre></div>
<p>Of course you have to remember to rename the module of <code>src/HolyProject.hs</code>. I separated all functions in different submodules:</p>
<ul>
<li><code>HolyProject.GitConfig</code>
<ul>
<li><code>getNameAndMailFromGitConfig</code>: retrieve name an email from <code>.gitconfig</code> file</li>
</ul></li>
<li><code>HolyProject.GithubAPI</code>
<ul>
<li><code>searchGHUser</code>: retrieve github user name using github API.</li>
</ul></li>
<li><code>HolyProject.MontyPython</code>
<ul>
<li><code>bk</code>: bridge keeper speaks</li>
<li><code>you</code>: you speak</li>
<li><code>ask</code>: Ask a question and wait for an answer</li>
</ul></li>
<li><code>HolyProject.StringUtils</code>: String helper functions
<ul>
<li><code>projectNameFromString</code></li>
<li><code>capitalize</code></li>
<li><code>checkProjectName</code></li>
</ul></li>
</ul>
<p>The <code>HolyProject.hs</code> file contains mostly the code that ask questions, show errors and copy files using hastache.</p>
<p>One of the benefits in modularizing the code is that our main code is clearer. Some functions are declared only in a module and are not exported. This help us hide technical details. For example, the modification of the HTTP header to use the github API.</p>
<h3 id="documenting">Documenting</h3>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/holy-grenade.jpg" alt="The Holy Grenade" />
</div>
<p>We didnt take much advantage of the project structure yet. A first thing is to generate some documentation. Before most function I added comment starting with <code>-- |</code>. These comment will be used by haddock to create a documentation. First, you need to install <code>haddock</code> manually.</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb40-1" title="1"><span class="ex">cabal</span> install haddock</a></code></pre></div>
<p>Be sure to have <code>haddock</code> in your <code>PATH</code>. You could for example add it like this:</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb41-1" title="1"><span class="co"># You might want to add this line in your .profile</span></a>
<a class="sourceLine" id="cb41-2" title="2"><span class="bu">export</span> <span class="va">PATH=$PATH</span>:./.cabal-sandbox/bin</a></code></pre></div>
<p>And if you are at the root of your project youll get it. And now just launch:</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb42-1" title="1"><span class="ex">cabal</span> haddock</a></code></pre></div>
<p>And magically, youll have a documentation in <code>dist/doc/html/holy-project/index.html</code>.</p>
<h3 id="tests">Tests</h3>
<p>While the Haskell static typing is quite efficient to prevent entire classes of bugs, Haskell doesnt discard the need to test to minimize the number of bugs.</p>
<h4 id="unit-testing-with-hunit">Unit Testing with HUnit</h4>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/witch.jpg" alt="A Witch! A Witch!" />
</div>
<p>It is generally said to test we should use unit testing for code in IO and QuickCheck or SmallCheck for pure code.</p>
<p>A unit test example on pure code is in the file <code>test/HolyProject/Swallow/Test.hs</code>:</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb43-1" title="1"><span class="kw">module</span> <span class="dt">HolyProject.Swallow.Test</span></a>
<a class="sourceLine" id="cb43-2" title="2"> (swallowSuite)</a>
<a class="sourceLine" id="cb43-3" title="3"><span class="kw">where</span></a>
<a class="sourceLine" id="cb43-4" title="4"><span class="kw">import</span> <span class="dt">Test.Tasty</span> (testGroup, <span class="dt">TestTree</span>)</a>
<a class="sourceLine" id="cb43-5" title="5"><span class="kw">import</span> <span class="dt">Test.Tasty.HUnit</span></a>
<a class="sourceLine" id="cb43-6" title="6"><span class="kw">import</span> <span class="dt">HolyProject.Swallow</span> (<span class="highlight">swallow</span>)</a>
<a class="sourceLine" id="cb43-7" title="7"></a>
<a class="sourceLine" id="cb43-8" title="8"><span class="ot">swallowSuite ::</span> <span class="dt">TestTree</span></a>
<a class="sourceLine" id="cb43-9" title="9">swallowSuite <span class="ot">=</span> testGroup <span class="st">&quot;Swallow&quot;</span></a>
<a class="sourceLine" id="cb43-10" title="10"> [testCase <span class="st">&quot;swallow test&quot;</span> testSwallow]</a>
<a class="sourceLine" id="cb43-11" title="11"></a>
<a class="sourceLine" id="cb43-12" title="12"><span class="co">-- in Swallow: swallow = (++)</span></a>
<a class="sourceLine" id="cb43-13" title="13"><span class="ot">testSwallow ::</span> <span class="dt">Assertion</span></a>
<a class="sourceLine" id="cb43-14" title="14">testSwallow <span class="ot">=</span> <span class="st">&quot;something&quot;</span> <span class="op">@=?</span> <span class="highlight">swallow</span> <span class="st">&quot;some&quot;</span> <span class="st">&quot;thing&quot;</span></a></code></pre></div>
<p>Note <code>swallow</code> is <code>(++)</code>. We group tests by group. Each group can contain some test suite. Here we have a test suite with only one test. The <code>(@=?)</code> verify the equality between its two parameters.</p>
<p>So now, we could safely delete the directory <code>test/HolyProject/Swallow</code> and the file <code>src/HolyProject/Swallow.hs</code>. And we are ready to make our own real world unit test. We will first test the module <code>HolyProject.GithubAPI</code>. Lets create a file <code>test/HolyProject/GithubAPI/Test.hs</code> with the following content:</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb44-1" title="1"><span class="kw">module</span> <span class="dt">HolyProject.GithubAPI.Test</span></a>
<a class="sourceLine" id="cb44-2" title="2">( githubAPISuite</a>
<a class="sourceLine" id="cb44-3" title="3">) <span class="kw">where</span></a>
<a class="sourceLine" id="cb44-4" title="4"><span class="kw">import</span> <span class="dt">Test.Tasty</span> (testGroup, <span class="dt">TestTree</span>)</a>
<a class="sourceLine" id="cb44-5" title="5"><span class="kw">import</span> <span class="dt">Test.Tasty.HUnit</span></a>
<a class="sourceLine" id="cb44-6" title="6"><span class="kw">import</span> <span class="dt">HolyProject.GithubAPI</span></a>
<a class="sourceLine" id="cb44-7" title="7"></a>
<a class="sourceLine" id="cb44-8" title="8"><span class="ot">githubAPISuite ::</span> <span class="dt">TestTree</span></a>
<a class="sourceLine" id="cb44-9" title="9">githubAPISuite <span class="ot">=</span> testGroup <span class="st">&quot;GithubAPI&quot;</span></a>
<a class="sourceLine" id="cb44-10" title="10"> [ testCase <span class="st">&quot;Yann&quot;</span> <span class="op">$</span> ioTestEq</a>
<a class="sourceLine" id="cb44-11" title="11"> (searchGHUser <span class="st">&quot;Yann.Esposito@gmail.com&quot;</span>)</a>
<a class="sourceLine" id="cb44-12" title="12"> (<span class="dt">Just</span> <span class="st">&quot;\&quot;yogsototh\&quot;&quot;</span>)</a>
<a class="sourceLine" id="cb44-13" title="13"> , testCase <span class="st">&quot;Jasper&quot;</span> <span class="op">$</span> ioTestEq</a>
<a class="sourceLine" id="cb44-14" title="14"> (searchGHUser <span class="st">&quot;Jasper Van der Jeugt&quot;</span>)</a>
<a class="sourceLine" id="cb44-15" title="15"> (<span class="dt">Just</span> <span class="st">&quot;\&quot;jaspervdj\&quot;&quot;</span>)</a>
<a class="sourceLine" id="cb44-16" title="16"> ]</a>
<a class="sourceLine" id="cb44-17" title="17"></a>
<a class="sourceLine" id="cb44-18" title="18"><span class="co">-- | Test if some IO action returns some expected value</span></a>
<a class="sourceLine" id="cb44-19" title="19"><span class="ot">ioTestEq ::</span> (<span class="dt">Eq</span> a, <span class="dt">Show</span> a) <span class="ot">=&gt;</span> <span class="dt">IO</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Assertion</span></a>
<a class="sourceLine" id="cb44-20" title="20">ioTestEq action expected <span class="ot">=</span> action <span class="op">&gt;&gt;=</span> assertEqual <span class="st">&quot;&quot;</span> expected</a></code></pre></div>
<p>You have to modify your cabal file. More precisely, you have to add <code>HolyProject.GithubAPI</code> in the exposed modules of the library secion). You also have to update the <code>test/Test.hs</code> file to use <code>GithubAPI</code> instead of <code>Swallow</code>.</p>
<p>So we have our example of unit testing using IO. We search the github nickname for some people I know and we verify github continue to give the same answer as expected.</p>
<h4 id="property-testing-with-smallcheck-and-quickcheck">Property Testing with SmallCheck and QuickCheck</h4>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/zoot.jpg" alt="My name is Zoot. Just Zoot" />
</div>
<p>When it comes to pure code, a very good method is to use QuickCheck and SmallCheck. SmallCheck will verify all cases up to some depth about some property. While QuickCheck will verify some random cases.</p>
<p>As this kind of verification of property is mostly doable on pure code, we will test the <code>StringUtils</code> module.</p>
<p>So dont forget to declare <code>HolyProject.StringUtils</code> in the exposed modules in the library section of your cabal file. Remove all references to the <code>Coconut</code> module.</p>
<p>Modify the <code>test/Test.hs</code> to remove all references about <code>Coconut</code>. Create a <code>test/HolyProject/StringUtils/Test.hs</code> file containing:</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode haskell"><code class="sourceCode haskell"><a class="sourceLine" id="cb45-1" title="1"><span class="kw">module</span> <span class="dt">HolyProject.StringUtils.Test</span></a>
<a class="sourceLine" id="cb45-2" title="2">( stringUtilsSuite</a>
<a class="sourceLine" id="cb45-3" title="3">) <span class="kw">where</span></a>
<a class="sourceLine" id="cb45-4" title="4"><span class="kw">import</span> <span class="dt">Test.Tasty</span> (testGroup, <span class="dt">TestTree</span>)</a>
<a class="sourceLine" id="cb45-5" title="5"><span class="kw">import</span> <span class="dt">Test.Tasty.SmallCheck</span> (forAll)</a>
<a class="sourceLine" id="cb45-6" title="6"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Test.Tasty.SmallCheck</span> <span class="kw">as</span> <span class="dt">SC</span></a>
<a class="sourceLine" id="cb45-7" title="7"><span class="kw">import</span> <span class="kw">qualified</span> <span class="dt">Test.Tasty.QuickCheck</span> <span class="kw">as</span> <span class="dt">QC</span></a>
<a class="sourceLine" id="cb45-8" title="8"><span class="kw">import</span> <span class="dt">Test.SmallCheck.Series</span> (<span class="dt">Serial</span>)</a>
<a class="sourceLine" id="cb45-9" title="9"><span class="kw">import</span> <span class="dt">HolyProject.StringUtils</span></a>
<a class="sourceLine" id="cb45-10" title="10"></a>
<a class="sourceLine" id="cb45-11" title="11"><span class="ot">stringUtilsSuite ::</span> <span class="dt">TestTree</span></a>
<a class="sourceLine" id="cb45-12" title="12">stringUtilsSuite <span class="ot">=</span> testGroup <span class="st">&quot;StringUtils&quot;</span></a>
<a class="sourceLine" id="cb45-13" title="13"> [ SC.testProperty <span class="st">&quot;SC projectNameFromString idempotent&quot;</span> <span class="op">$</span></a>
<a class="sourceLine" id="cb45-14" title="14"> idempotent projectNameFromString</a>
<a class="sourceLine" id="cb45-15" title="15"> , SC.testProperty <span class="st">&quot;SC capitalize idempotent&quot;</span> <span class="op">$</span></a>
<a class="sourceLine" id="cb45-16" title="16"> deeperIdempotent capitalize</a>
<a class="sourceLine" id="cb45-17" title="17"> , QC.testProperty <span class="st">&quot;QC projectNameFromString idempotent&quot;</span> <span class="op">$</span></a>
<a class="sourceLine" id="cb45-18" title="18"> idempotent capitalize</a>
<a class="sourceLine" id="cb45-19" title="19"> ]</a>
<a class="sourceLine" id="cb45-20" title="20"></a>
<a class="sourceLine" id="cb45-21" title="21">idempotent f <span class="ot">=</span> \s <span class="ot">-&gt;</span> f s <span class="op">==</span> f (f s)</a>
<a class="sourceLine" id="cb45-22" title="22"></a>
<a class="sourceLine" id="cb45-23" title="23"><span class="ot">deeperIdempotent ::</span> (<span class="dt">Eq</span> a, <span class="dt">Show</span> a, <span class="dt">Serial</span> m a) <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> <span class="dt">SC.Property</span> m</a>
<a class="sourceLine" id="cb45-24" title="24">deeperIdempotent f <span class="ot">=</span> forAll <span class="op">$</span> SC.changeDepth1 (<span class="op">+</span><span class="dv">1</span>) <span class="op">$</span> \s <span class="ot">-&gt;</span> f s <span class="op">==</span> f (f s)</a></code></pre></div>
<p>The result is here:</p>
<pre>
All Tests
StringUtils
SC projectNameFromString idempotent: <span class="green">OK</span>
206 tests completed
SC capitalize idempotent: <span class="green">OK</span>
1237 tests completed
QC projectNameFromString idempotent: <span class="red">FAIL</span>
*** Failed! Falsifiable (after 19 tests and 5 shrinks):
"a a"
Use --quickcheck-replay '18 913813783 2147483380' to reproduce.
GithubAPI
Yann: <span class="green">OK</span>
Jasper: <span class="green">OK</span>
<span class="red">1 out of 5 tests failed</span>
</pre>
<p>The test fail, but this is not an error. Our <code>capitalize</code> function shouldnt be idempotent. I simply added this test to show what occurs when a test fail. If you want to look more closely to the error you could do this:</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode bash"><code class="sourceCode bash"><a class="sourceLine" id="cb46-1" title="1">$ <span class="ex">./interact</span></a>
<a class="sourceLine" id="cb46-2" title="2"><span class="ex">GHCi</span>, version 7.6.2: http://www.haskell.org/ghc/ :? for help</a>
<a class="sourceLine" id="cb46-3" title="3"><span class="ex">Loading</span> package ghc-prim ... linking ... done.</a>
<a class="sourceLine" id="cb46-4" title="4"><span class="ex">Loading</span> package integer-gmp ... linking ... done.</a>
<a class="sourceLine" id="cb46-5" title="5"><span class="ex">Loading</span> package base ... linking ... done.</a>
<a class="sourceLine" id="cb46-6" title="6"><span class="ex">Prelude</span><span class="op">&gt;</span> :l src/HolyProject/StringUtils</a>
<a class="sourceLine" id="cb46-7" title="7">[<span class="ex">1</span> of 1] Compiling HolyProject.StringUtils ( src/HolyProject/StringUtils.hs, interpreted )</a>
<a class="sourceLine" id="cb46-8" title="8"><span class="ex">Ok</span>, modules loaded: HolyProject.StringUtils.</a>
<a class="sourceLine" id="cb46-9" title="9"><span class="ex">*HolyProject.StringUtils</span><span class="op">&gt;</span> capitalize <span class="st">&quot;a a&quot;</span></a>
<a class="sourceLine" id="cb46-10" title="10"><span class="dt"><span class="highlight"></span><span class="st">&quot;AA&quot;</span><span class="dt"></span></span></a>
<a class="sourceLine" id="cb46-11" title="11"><span class="ex">*HolyProject.StringUtils</span><span class="op">&gt;</span> capitalize (capitalize <span class="st">&quot;a a&quot;</span>)</a>
<a class="sourceLine" id="cb46-12" title="12"><span class="dt"><span class="highlight"></span><span class="st">&quot;Aa&quot;</span><span class="dt"></span></span></a>
<a class="sourceLine" id="cb46-13" title="13"><span class="ex">*HolyProject.StringUtils</span><span class="op">&gt;</span></a></code></pre></div>
<p>It is important to use <code>./interact</code> instead of <code>ghci</code>. Because we need to tell <code>ghci</code> how to found the package installed.</p>
<p>Apparently, SmallCheck didnt found any counter example. I dont know how it generates Strings and using deeper search is really long.</p>
<h2 id="conclusion">Conclusion</h2>
<div>
<img src="../../../../Scratch/img/blog/Holy-Haskell-Starter/a-blessing.jpg" alt="Rabbit" />
</div>
<p>Congratulation!</p>
<p>Now you could start programming in Haskell and publish your own cabal package.</p>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>For example, you have to install the test libraries manually to use <code>cabal test</code>.<a href="#fnref1" class="footnote-back"></a></p></li>
<li id="fn2"><p>There is no easy way to do something like <code>name=$(ask name)</code>. Simply because <code>$(ask name)</code> run in another process which doesnt get access to the standard input<a href="#fnref2" class="footnote-back"></a></p></li>
<li id="fn3"><p>Having a good level of power in templates is very difficult. <span class="sc"><abbr title="In my Humble Opinion">imho</abbr></span> Mustache has made the best compromise.<a href="#fnref3" class="footnote-back"></a></p></li>
</ol>
</section>
</div>
<div id="afterarticle">
<div id="social">
<a href="/rss.xml" target="_blank" rel="noopener noreferrer nofollow" class="social">RSS</a>
·
<a href="https://twitter.com/home?status=http%3A%2F%2Fyannesposito.com/Scratch/en/blog/Holy-Haskell-Starter/%20via%20@yogsototh" target="_blank" rel="noopener noreferrer nofollow" class="social">Tweet</a>
·
<a href="http://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fyannesposito.com/Scratch/en/blog/Holy-Haskell-Starter/" target="_blank" rel="noopener noreferrer nofollow" class="social">FB</a>
<br />
<a class="message" href="../../../../Scratch/en/blog/Social-link-the-right-way/">These social sharing links preserve your privacy</a>
</div>
<div id="navigation">
<a href="../../../../">Home</a>
<span class="sep">¦</span>
<a href="../../../../Scratch/en/blog">Blog</a>
<span class="sep">¦</span>
<a href="../../../../Scratch/en/softwares">Softwares</a>
<span class="sep">¦</span>
<a href="../../../../Scratch/en/about">About</a>
</div>
<div id="totop"><a href="#header">↑ Top ↑</a></div>
<div id="bottom">
<div>
Published on 2013-11-14
</div>
<div>
<a href="https://twitter.com/yogsototh">Follow @yogsototh</a>
</div>
<div>
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_US">Yann Esposito©</a>
</div>
<div>
Done with
<a href="http://www.vim.org" target="_blank" rel="noopener noreferrer nofollow"><strike>Vim</strike></a>
<a href="http://spacemacs.org" target="_blank" rel="noopener noreferrer nofollow">spacemacs</a>
<span class="pala">&amp;</span>
<a href="http://nanoc.ws" target="_blank" rel="noopener noreferrer nofollow"><strike>nanoc</strike></a>
<a href="http://jaspervdj.be/hakyll" target="_blank" rel="noopener noreferrer nofollow">Hakyll</a>
</div>
<hr />
<div style="max-width: 100%">
<a href="https://cardanohub.org">
<img src="../../../../Scratch/img/ada-logo.png" class="simple" style="height: 16px;
border-radius: 50%;
vertical-align:middle;
display:inline-block;" />
ADA:
</a>
<code style="display:inline-block;
word-wrap:break-word;
text-align: left;
vertical-align: top;
max-width: 85%;">
DdzFFzCqrhtAvdkmATx5Fm8NPJViDy85ZBw13p4XcNzVzvQg8e3vWLXq23JQWFxPEXK6Kvhaxxe7oJt4VMYHxpA2vtCFiP8fziohN6Yp
</code>
</div>
</div>
</div>
</div>
</div>
</body>
</html>