<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alp Mestan :: Blog &#187; Programmation Fonctionnelle</title>
	<atom:link href="https://blog.developpez.com/alp/pcategory/programmation-fonctionnelle/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/alp</link>
	<description></description>
	<lastBuildDate>Fri, 28 Aug 2009 11:58:57 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>(Petit) Clône de client telnet en Haskell</title>
		<link>https://blog.developpez.com/alp/p7996/programmation-fonctionnelle/petit_clone_de_client_telnet_en_haskell</link>
		<comments>https://blog.developpez.com/alp/p7996/programmation-fonctionnelle/petit_clone_de_client_telnet_en_haskell#comments</comments>
		<pubDate>Fri, 28 Aug 2009 11:58:57 +0000</pubDate>
		<dc:creator><![CDATA[Alp]]></dc:creator>
				<category><![CDATA[Programmation Fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Bonjour, L&#8217;autre nuit, muni de café, j&#8217;ai souhaité m&#8217;amuser avec Haskell. J&#8217;ai alors consulté le chapitre sur le réseau en Haskell de Real World Haskell et&#8230; j&#8217;ai écrit un (très petit) clône de client telnet&#8230; qui fait 41 lignes. Le seul soucis étant que dans toute application de ce genre, on doit partager habilement la lecture des entrées de l&#8217;utilisateur, et l&#8217;affichage de ce que l&#8217;on nous envoie. Ceci mis à part, tout cela fonctionne [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Bonjour,</p>
<p>L&rsquo;autre nuit, muni de café, j&rsquo;ai souhaité m&rsquo;amuser avec Haskell. J&rsquo;ai alors consulté le chapitre sur le réseau en Haskell de <a href="http://book.realworldhaskell.org/read/">Real World Haskell</a> et&#8230; j&rsquo;ai écrit un (très petit) clône de client telnet&#8230; qui fait 41 lignes. Le seul soucis étant que dans toute application de ce genre, on doit partager habilement la lecture des entrées de l&rsquo;utilisateur, et l&rsquo;affichage de ce que l&rsquo;on nous envoie. Ceci mis à part, tout cela fonctionne très bien !</p>
<p><center><img src="http://haskell.org/logos/logos/logo7000.png" alt="Haskell" title="Haskell" /></center></p>
<p><span id="more-45"></span></p>
<p>Regardons à quoi cela ressemble. Petit détail : à chaque tour, je lance la réception de données réseau dans un autre thread, pour ne pas bloquer l&rsquo;écriture de l&rsquo;utilisateur.</p>
<p>On importe d&rsquo;abord les modules nécessaires.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">import Control.Concurrent <br />
import Control.Monad <br />
import Network.Socket <br />
import Network.BSD <br />
import System.Environment <br />
import System.IO</div></div>
<p>Ensuite, j&rsquo;ai écrit quelques fonctions pour rendre la connection, l&rsquo;envoi etc plus faciles.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-- Ouverture d'une connexion TCP cliente <br />
-- Prend en argument l'host et le port/service (qui est une String également) <br />
-- Retourne le &quot;Handle&quot; vers le socket en question. <br />
openConnection :: String -&gt; ServiceName -&gt; IO Handle <br />
openConnection hostname port = <br />
&nbsp; &nbsp; do <br />
&nbsp; &nbsp; &nbsp; addrInfos &lt;- getAddrInfo Nothing (Just hostname) (Just port) <br />
&nbsp; &nbsp; &nbsp; let serveraddr = head addrInfos <br />
&nbsp; &nbsp; &nbsp; sock &lt;- socket (addrFamily serveraddr) Stream defaultProtocol <br />
&nbsp; &nbsp; &nbsp; setSocketOption sock KeepAlive 1 <br />
&nbsp; &nbsp; &nbsp; connect sock (addrAddress serveraddr) <br />
&nbsp; &nbsp; &nbsp; h &lt;- socketToHandle sock ReadWriteMode <br />
&nbsp; &nbsp; &nbsp; hSetBuffering h (BlockBuffering Nothing) <br />
&nbsp; &nbsp; &nbsp; return h <br />
&nbsp;<br />
-- Ferme la connexion dont le Handle est donné <br />
closeConnection :: Handle -&gt; IO () <br />
closeConnection h = hClose h <br />
&nbsp;<br />
-- Envoie la chaîne donnée sur le Handle donné, et ensuite fait un flush sur ce handle, ce qui force l'envoi immédiat et nettoie les états <br />
sendMsg :: Handle -&gt; String -&gt; IO () <br />
sendMsg h msg = hPutStrLn h msg &gt;&gt; hFlush h <br />
&nbsp;<br />
-- Lis sur le Handle donné une chaîne et la renvoie (dans la monade IO) <br />
recvMsg :: Handle -&gt; IO String <br />
recvMsg h = do <br />
&nbsp; msg &lt;- hGetContents h &nbsp;<br />
&nbsp; return msg</div></div>
<p>Voyons maintenant la fonction main.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">main = do <br />
&nbsp; args &lt;- getArgs <br />
&nbsp; let (host, port) = (args !! 0, args !! 1)</div></div>
<p>On récupère les arguments donnés au programme (s&rsquo;il n&rsquo;y en a pas assez, cela fera planter le logiciel &#8212; je ne me suis pas vraiment préoccupé de tous les cas d&rsquo;erreur, mais ce n&rsquo;était pas ma priorité ici) via la fonction getArgs, et l&rsquo;on en récupère l&rsquo;host et le port donnés.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; putStrLn $ &quot;Opening client on &quot; ++ host ++ &quot;:&quot; ++ port ++ &quot;\n&quot; <br />
&nbsp; hclient &lt;- openConnection host port <br />
&nbsp; putStrLn &quot;Client connected&quot;</div></div>
<p>Ca y est, on se connecte, en affichant des messages pour tenir l&rsquo;utilisateur informé. Si la connection échoue, le programme s&rsquo;arrêtera avec une erreur &#8212; cf remarque ci-dessus.</p>
<p>Et maintenant, la boucle qui permet de lire depuis le réseau et lire depuis l&rsquo;utilisateur, etc.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; forever $ do <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getLine &gt;&gt;= sendMsg hclient <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;forkIO $ recvMsg hclient &gt;&gt;= putStrLn</div></div>
<p>Ici, on a une sorte de boucle &laquo;&nbsp;à la while(true)&nbsp;&raquo;, dans laquelle on va tour à tour récupérer une entrée de l&rsquo;utilisateur et l&rsquo;envoyer au serveur, puis, dans un thread séparé, récupérer ce qu&rsquo;a envoyé le serveur et l&rsquo;afficher.<br />
Enfin, on ferme la connection (ce code est inutile tant que l&rsquo;on a pas de possibilité de sortir du forever&#8230; qui devra tôt ou tard se transformer en &laquo;&nbsp;until&nbsp;&raquo; ou autre).</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; closeConnection hclient</div></div>
<p>Voilà donc le code complet :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">import Control.Concurrent <br />
import Control.Monad <br />
import Network.Socket <br />
import Network.BSD <br />
import System.Environment <br />
import System.IO <br />
&nbsp;<br />
openConnection :: String -&gt; ServiceName -&gt; IO Handle <br />
openConnection hostname port = <br />
&nbsp; &nbsp; do <br />
&nbsp; &nbsp; &nbsp; addrInfos &lt;- getAddrInfo Nothing (Just hostname) (Just port) <br />
&nbsp; &nbsp; &nbsp; let serveraddr = head addrInfos <br />
&nbsp; &nbsp; &nbsp; sock &lt;- socket (addrFamily serveraddr) Stream defaultProtocol <br />
&nbsp; &nbsp; &nbsp; setSocketOption sock KeepAlive 1 <br />
&nbsp; &nbsp; &nbsp; connect sock (addrAddress serveraddr) <br />
&nbsp; &nbsp; &nbsp; h &lt;- socketToHandle sock ReadWriteMode <br />
&nbsp; &nbsp; &nbsp; hSetBuffering h (BlockBuffering Nothing) <br />
&nbsp; &nbsp; &nbsp; return h <br />
&nbsp;<br />
closeConnection :: Handle -&gt; IO () <br />
closeConnection h = hClose h <br />
&nbsp;<br />
sendMsg :: Handle -&gt; String -&gt; IO () <br />
sendMsg h msg = hPutStrLn h msg &gt;&gt; hFlush h <br />
&nbsp;<br />
recvMsg :: Handle -&gt; IO String <br />
recvMsg h = do <br />
&nbsp; msg &lt;- hGetContents h &nbsp;<br />
&nbsp; return msg <br />
&nbsp;<br />
main = do <br />
&nbsp; args &lt;- getArgs <br />
&nbsp; let (host, port) = (args !! 0, args !! 1) <br />
&nbsp; putStrLn $ &quot;Opening client on &quot; ++ host ++ &quot;:&quot; ++ port ++ &quot;\n&quot; <br />
&nbsp; hclient &lt;- openConnection host port <br />
&nbsp; putStrLn &quot;Client connected&quot; <br />
&nbsp; forever $ do <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getLine &gt;&gt;= sendMsg hclient <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;forkIO $ recvMsg hclient &gt;&gt;= putStrLn <br />
&nbsp; closeConnection hclient</div></div>
<p>Pour compiler (j&rsquo;ai tout ce code dans un fichier net.hs :<br />
<code class="codecolorer text default"><span class="text">ghc --make -o net net.hs</span></code><br />
Puis 2 exemples d&rsquo;exécution&#8230;</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./net google.fr 80 <br />
Opening client on google.fr:80 <br />
&nbsp;<br />
Client connected <br />
GET / HTTP/1.0 <br />
&nbsp;<br />
HTTP/1.0 302 Found <br />
Location: http://www.google.fr/ <br />
Cache-Control: private <br />
Content-Type: text/html; charset=UTF-8 <br />
Set-Cookie: PREF=ID=30b094ad566b5532:TM=1251456529:LM=1251456529:S=94IXp5-SGiaYADWc; expires=Sun, 28-Aug-2011 10:48:49 GMT; path=/; domain=.google.com <br />
Date: Fri, 28 Aug 2009 10:48:49 GMT <br />
Server: gws <br />
Content-Length: 218 <br />
&nbsp;<br />
&lt;HTML&gt;&lt;HEAD&gt;&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html;charset=utf-8&quot;&gt; <br />
&lt;TITLE&gt;302 Moved&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY&gt; <br />
&lt;H1&gt;302 Moved&lt;/H1&gt; <br />
The document has moved <br />
&lt;A HREF=&quot;http://www.google.fr/&quot;&gt;here&lt;/A&gt;. <br />
&lt;/BODY&gt;&lt;/HTML&gt; <br />
&nbsp;<br />
^C</div></div>
<p>(c&rsquo;est moi qui ai tapé &laquo;&nbsp;GET / HTTP/1.0&Prime;)<br />
( qui vous dira que la page a été déplacée <img src="https://blog.developpez.com/alp/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /> )</p>
<p>Et enfin, la surprise&#8230;</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ./net towel.blinkenlights.nl 23</div></div>
<p>Qui, une version simplifiée d&rsquo;un film très connu, vous permettra de voir, Jedi.</p>
<p>Enjoy !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Haskell Platform, ou comment se mettre à Haskell sans soucis !</title>
		<link>https://blog.developpez.com/alp/p7977/programmation-fonctionnelle/haskell_platform_ou_comment_se_mettre_a_</link>
		<comments>https://blog.developpez.com/alp/p7977/programmation-fonctionnelle/haskell_platform_ou_comment_se_mettre_a_#comments</comments>
		<pubDate>Mon, 24 Aug 2009 16:22:37 +0000</pubDate>
		<dc:creator><![CDATA[Alp]]></dc:creator>
				<category><![CDATA[Programmation Fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Bonjour à tous, Cela fait quelques temps maintenant que la communauté Haskell a sorti Haskell Platform. Il s&#8217;agit d&#8217;un &#171;&#160;paquet&#160;&#187; qui regroupe : &#8211; le compilateur haskell GHC, un debugger, un profiler, etc &#8211; les bibliothèques les plus populaires et les plus utilisées, fournies d&#8217;office &#8211; tout un tas d&#8217;outils auxiliaires, comme haddock, qui permet de générer de la documentation depuis les commentaires du code source (comme doxygen pour le C++). Le tout se configurant [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Bonjour à tous,</p>
<p>Cela fait quelques temps maintenant que la communauté <a href="http://www.haskell.org/">Haskell</a> a sorti <strong><a href="http://hackage.haskell.org/platform/">Haskell Platform</a></strong>. Il s&rsquo;agit d&rsquo;un &laquo;&nbsp;paquet&nbsp;&raquo; qui regroupe :<br />
&#8211; le compilateur haskell GHC, un debugger, un profiler, etc<br />
&#8211; les bibliothèques les plus populaires et les plus utilisées, fournies d&rsquo;office<br />
&#8211; tout un tas d&rsquo;outils auxiliaires, comme <em>haddock</em>, qui permet de générer de la documentation depuis les commentaires du code source (comme <strong>doxygen</strong> pour le C++).</p>
<p><center><img src="http://haskell.org/sitewiki/images/thumb/7/7d/Platform.png/300px-Platform.png" alt="Haskell Platform" title="Haskell Platform" /></center></p>
<p>Le tout se configurant automatiquement, bien évidemment.</p>
<p><span id="more-44"></span></p>
<p>Il existe des paquets pour déjà quelques distributions Linux, sachant que ce sera bientôt prêt pour Debian et Ubuntu également. Les installeurs Windows et Mac sont très simples également.</p>
<p>Bref, plus aucune raison de ne pas essayer Haskell <img src="https://blog.developpez.com/alp/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
<p>Par la suite, vous pourrez donc par exemple lancer le toplevel associé, nommé <strong>ghci</strong>, en lançant par exemple depuis un invite de commande sous Windows, ou depuis n&rsquo;importe quel terminal sous les systèmes UNIX-like :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ ghci <br />
GHCi, version 6.10.4: http://www.haskell.org/ghc/ &nbsp;:? for help <br />
Loading package ghc-prim ... linking ... done. <br />
Loading package integer ... linking ... done. <br />
Loading package base ... linking ... done.</div></div>
<p>Et vous pourrez ensuite commencer à vous amuser avec ghci :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Prelude&gt; 42^42 <br />
150130937545296572356771972164254457814047970568738777235893533016064 <br />
Prelude&gt; foldr (+) 0 [1,2,3,4,5,6] <br />
21 <br />
Prelude&gt; &quot;Salut&quot; ++ &quot; Developpez !&quot; &nbsp; <br />
&quot;Salut Developpez !&quot;</div></div>
<p>Pour rappel, si vous désirez apprendre Haskell :<br />
> http://gorgonite.developpez.com/livres/traductions/haskell/gentle-haskell/ (fr)<br />
> http://book.realworldhaskell.org/read/ (en)</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Récupération et traitement d&#8217;un flux Atom XML en Haskell</title>
		<link>https://blog.developpez.com/alp/p7752/programmation-fonctionnelle/recuperation_et_traitement_d_un_flux_ato</link>
		<comments>https://blog.developpez.com/alp/p7752/programmation-fonctionnelle/recuperation_et_traitement_d_un_flux_ato#comments</comments>
		<pubDate>Tue, 16 Jun 2009 03:20:10 +0000</pubDate>
		<dc:creator><![CDATA[Alp]]></dc:creator>
				<category><![CDATA[Programmation Fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Bonsoir, Il y a peu, on m&#8217;a demandé d&#8217;écrire un programme qui récupère un flux Atom XML et qui ne récupère que le titre et l&#8217;url des éléments (qui en l&#8217;occurence sont des billets aggrégés sur Planet OCaml). J&#8217;ai hésité entre OCaml, C++ et Haskell. Plutôt tenté par du fonctionnel, mon choix s&#8217;est vite porté sur Haskell grâce au nombre impressionnant de paquets présents sur Hackage. J&#8217;ai donc opté pour le paquet feed pour la [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Bonsoir,</p>
<p>Il y a peu, on m&rsquo;a demandé d&rsquo;écrire un programme qui récupère un flux Atom XML et qui ne récupère que le titre et l&rsquo;url des éléments (qui en l&rsquo;occurence sont des billets aggrégés sur <a href="http://planet.ocamlcore.org/">Planet OCaml</a>).</p>
<p>J&rsquo;ai hésité entre OCaml, C++ et Haskell. Plutôt tenté par du fonctionnel, mon choix s&rsquo;est vite porté sur Haskell grâce au nombre impressionnant de paquets présents sur Hackage.<br />
J&rsquo;ai donc opté pour le paquet <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/feed-0.3.6">feed</a> pour la gestion d&rsquo;Atom et <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/download">download</a> pour la récupération du XML distant, qui se situe <a href="http://planet.ocamlcore.org/atom.xml">ici</a>).</p>
<p><center><img alt="Haskell Logo" src="http://www.haskell.org/sitewiki/images/8/86/Haskellwiki_logo_big.png" title="Haskell Logo"/></center></p>
<p><span id="more-43"></span></p>
<p>Alors, voyons voir&#8230; Premièrement, on importe les modules dont on a besoin, évidemment.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">import Network.Download <br />
import Text.Atom.Feed <br />
import Text.Feed.Import <br />
import Text.Feed.Types</div></div>
<p>Ensuite, on définit l&rsquo;adresse du fichier atom.xml&#8230; Toujours rien de bien sorcier.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">url = &quot;http://planet.ocamlcore.org/atom.xml&quot;</div></div>
<p>Puis on se lance dans main !</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">main = do <br />
&nbsp; &nbsp; putStrLn &quot;*** Recent blog posts ***&quot; <br />
&nbsp; &nbsp; Right src &lt;- openURIString url</div></div>
<p>Ici, on affiche simplement un message dans la console, puis on récupère le contenu du fichier dans la chaîne de caractères <em>src</em>.<br />
<strong>Right</strong> est l&rsquo;un des constructeurs du type <a href="http://hackage.haskell.org/packages/archive/base/4.1.0.0/doc/html/Data-Either.html#t%3AEither"><strong>Either</strong></a>, ne vous en préoccupez pas trop.</p>
<p>Ensuite, on s&rsquo;occupe à proprement parler du flux Atom&#8230;</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">let Just (AtomFeed is) = parseFeedString src</div></div>
<p><strong>Just</strong> est un constructeur du type <a href="http://hackage.haskell.org/packages/archive/base/4.1.0.0/doc/html/Data-Maybe.html#t%3AMaybe"><strong>Maybe</strong></a>, qui permet de gérer les erreurs (Just mavaleur si pas eu d&rsquo;erreur, Nothing si une erreur). AtomFeed est lui un constructeur pour le type <a href="http://hackage.haskell.org/packages/archive/feed/0.3.6/doc/html/Text-Feed-Types.html#t%3AFeed"><strong>Feed</strong></a> précisant que c&rsquo;est un flux Atom, et non RSS1 ou RSS2 par exemple (qui sont eux aussi gérés par ce même paquet). La fonction <em>parseFeedString</em> prend donc une chaîne (ici <em>src</em>) et retourne un flux Atom&#8230; C&rsquo;est là, en utilisant <em>is</em>, que l&rsquo;on va pouvoir récupérer les différents éléments du XML au format Atom.</p>
<p>Bon, et si on récupérait les différentes entrées de notre flux (ici ce sont des billets de blog) ?</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">let entries = feedEntries is</div></div>
<p>Ceci nous retourne donc une liste d&rsquo;<a href="http://hackage.haskell.org/packages/archive/feed/0.3.6/doc/html/Text-Atom-Feed.html#t%3AEntry"><strong>Entry</strong></a>. Et c&rsquo;est parti, on va récupérer les informations qu&rsquo;il nous faut, puis les afficher !</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">let infos = map (\e -&gt; (entryTitle e, entryId e)) entries <br />
mapM_ (\(x,y) -&gt; putStrLn $ (stringize x) ++ &quot;: &quot; ++ y) infos</div></div>
<p>Oui, oui, ça se complique un peu.<br />
Tout d&rsquo;abord, qu&rsquo;est-ce que <em>infos</em> ? <em>map</em> transforme chaque élément en l&rsquo;image de l&rsquo;élément donné par son premier argument, qui est donc une fonction. Ici, on va transformer chaque <strong>Entry</strong> en un couple <em>(titre, id)</em> associé à notre entrée, où id se trouve être l&rsquo;URL originale du billet.<br />
Bon infos est donc la liste des couples (titre, url). Ah ? Ce n&rsquo;étant pas tellement cette ligne qui vous faisait peur mais la suivante ?<br />
Bon, sans rentrer en détail dans les monades (<a href="http://haskell.org/haskellwiki/Monad">la page Monad du HaskellWiki</a> le faisant mieux que moi, et surtout donnant d&rsquo;excellents liens pour comprendre de quoi il s&rsquo;agit, où c&rsquo;est utilisé, etc), on se trouve dans la monade IO. mapM_ se retrouve donc avec le type :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">(a -&gt; IO b) -&gt; [a] -&gt; IO ()</div></div>
<p>Notre <em>[a]</em>, c&rsquo;est infos, donc notre liste de couples&#8230;<br />
<em>(a -> IO b)</em> est effectivement le type de notre fonction anonyme, que je me permets de vous montrer à part ici :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">\(x,y) -&gt; putStrLn $ (stringize x) ++ &quot;: &quot; ++ y</div></div>
<p>A un couple (titre,url), elle associe un appel à <em>putStrLn</em>, qui retourne <em>IO ()</em>. Donc le type <em>b</em> est en fait <em>()</em>. <em>mapM_</em> ne faut qu&rsquo;effectuer des actions dans une monade donnée, en ignorant le résultat de chacune au lieu de les placer des une liste comme le fait son homologue <em>mapM</em></p>
<p>Ah oui, j&rsquo;oubliais, stringize, qui est définie juste après fonction main.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">stringize :: TextContent -&gt; String <br />
stringize (TextString s) = s <br />
stringize _ = error &quot;shoud not be called on something else than TextString&quot;</div></div>
<p>Elle me permet juste de passer d&rsquo;une valeur construite avec TextString, donc de type <a href="http://hackage.haskell.org/packages/archive/feed/0.3.6/doc/html/Text-Atom-Feed.html#t%3ATextContent"><strong>TextContent</strong></a>, à la valeur qui est en fait englobée par ce type, de type String.</p>
<p>Voilà donc le code complet :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">import Network.Download <br />
import Text.Atom.Feed <br />
import Text.Feed.Import <br />
import Text.Feed.Types <br />
&nbsp;<br />
url = &quot;http://planet.ocamlcore.org/atom.xml&quot; <br />
&nbsp;<br />
main = do <br />
&nbsp; &nbsp; putStrLn &quot;*** Recent blog posts ***&quot; <br />
&nbsp; &nbsp; Right src &lt;- openURIString url <br />
&nbsp; &nbsp; let Just (AtomFeed is) = parseFeedString src <br />
&nbsp; &nbsp; let entries = feedEntries is <br />
&nbsp; &nbsp; let infos = map (\e -&gt; (entryTitle e, entryId e)) entries <br />
&nbsp; &nbsp; mapM_ (\(x,y) -&gt; putStrLn $ (stringize x) ++ &quot;: &quot; ++ y) infos <br />
&nbsp;<br />
stringize :: TextContent -&gt; String <br />
stringize (TextString s) = s <br />
stringize _ = &quot;stringize Error&quot;</div></div>
<p>La compilation :</p>
<blockquote><p>$ ghc -package download -o cwn cwn.hs</p></blockquote>
<p>Et un exemple d&rsquo;execution :</p>
<blockquote><p>$ ./cwn<br />
*** Recent blog posts ***<br />
ocaml-text: http://forge.ocamlcore.org/projects/ocaml-text/<br />
0.1.3 sources now in subversion: http://forge.ocamlcore.org/forum/forum.php?forum_id=355<br />
Sudoku in ocamljs, part 2: RPC over HTTP: tag:blogger.com,1999:blog-1445545651031573301.post-3490486535879812384<br />
Caml Weekly News, 28 Apr 2009: http://alan.petitepomme.net/cwn/2009.04.28.html<br />
Bouncing Ball in OCaml with OCamlSDL: http://blog.mestan.fr/?p=31<br />
Sudoku in ocamljs, part 1: DOM programming: tag:blogger.com,1999:blog-1445545651031573301.post-4574121943207730951<br />
Using OCaml’s module functors to provide monadic contexts for Batteries: http://blog.mestan.fr/?p=30<br />
Lastfm no longer free as in free beer (and some bits about xml in OCaml): http://blog.rastageeks.org/spip.php?article34<br />
Last lecture: http://dutherenverseauborddelatable.wordpress.com/?p=571<br />
Liquidsoap now supports AAC+ encoding.: http://blog.rastageeks.org/spip.php?article33</p></blockquote>
<p>Alors, pas si &laquo;&nbsp;académique&nbsp;&raquo; que ça le fonctionnel, non ? <img src="https://blog.developpez.com/alp/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /><br />
Tout ça en 18 lignes, lignes vides comprises, 15 non comprises.</p>
<p>Enjoy.</p>
<p>PS : on pourrait raccourcir et rendre le code moins compréhensible en utilisant des opérateurs et moins de valeurs intermédiaires, mais ce n&rsquo;est pas l&rsquo;objectif ici.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hello Gtk2Hs !</title>
		<link>https://blog.developpez.com/alp/p7737/programmation-fonctionnelle/hello_gtk2hs</link>
		<comments>https://blog.developpez.com/alp/p7737/programmation-fonctionnelle/hello_gtk2hs#comments</comments>
		<pubDate>Fri, 12 Jun 2009 17:02:07 +0000</pubDate>
		<dc:creator><![CDATA[Alp]]></dc:creator>
				<category><![CDATA[Programmation Fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Bonjour, M&#8217;étant mis à Haskell depuis quelques temps (principalement grâce au désormais fameux Real World Haskell), je me suis dis qu&#8217;il était temps que je regarde un peu du côté des bibliothèques pour interfaces utilisateurs. Hé bien, je n&#8217;ai pas été déçu. Il y a notamment Gtk2Hs qui fournit un bon binding de GTK+, compatible avec Glade (le designer) et qui permet donc de charger des interfaces depuis du XML. Allez-y, devinez combien de lignes [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Bonjour,</p>
<p>M&rsquo;étant mis à Haskell depuis quelques temps (principalement grâce au désormais fameux <a href="http://general.developpez.com/livres/general/?page=prog-fonctionnelle#L9780596514983">Real World Haskell</a>), je me suis dis qu&rsquo;il était temps que je regarde un peu du côté des bibliothèques pour interfaces utilisateurs. Hé bien, je n&rsquo;ai pas été déçu. Il y a notamment <strong>Gtk2Hs</strong> qui fournit un bon binding de GTK+, compatible avec Glade (le designer) et qui permet donc de charger des interfaces depuis du XML.</p>
<p><center><img src="http://blog.developpez.com/media/gtk2hs.png" width="409" height="297" alt="Gtk2Hs en action" /></center></p>
<p><span id="more-42"></span></p>
<p>Allez-y, devinez combien de lignes il a fallu ?<br />
Initialiser le GUI, créer les widgets, &#8230; Hmm beaucoup ?</p>
<p>Hé bien non ! Le designer, Glade, exporte le &laquo;&nbsp;projet&nbsp;&raquo; suivant dans un XML.</p>
<p><center><img src="http://blog.developpez.com/media/glade.png" width="700" height="370" alt="Designer de fenêtres de GTK+" /></center></p>
<p>XML généré :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;?xml version=&quot;1.0&quot;?&gt; <br />
&lt;glade-interface&gt; <br />
&nbsp; &lt;!-- interface-requires gtk+ 2.16 --&gt; <br />
&nbsp; &lt;!-- interface-naming-policy project-wide --&gt; <br />
&nbsp; &lt;widget class=&quot;GtkWindow&quot; id=&quot;window1&quot;&gt; <br />
&nbsp; &nbsp; &lt;property name=&quot;title&quot; translatable=&quot;yes&quot;&gt;Hello, Developpez !&lt;/property&gt; <br />
&nbsp; &nbsp; &lt;property name=&quot;default_width&quot;&gt;400&lt;/property&gt; <br />
&nbsp; &nbsp; &lt;property name=&quot;default_height&quot;&gt;400&lt;/property&gt; <br />
&nbsp; &nbsp; &lt;child&gt; <br />
&nbsp; &nbsp; &nbsp; &lt;widget class=&quot;GtkButton&quot; id=&quot;yo&quot;&gt; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;property name=&quot;label&quot; translatable=&quot;yes&quot;&gt;Bonjour Developpez, comment vas-tu ? <br />
&nbsp;<br />
Je suis un programme Haskell qui utilise <br />
Gtk2Hs, binding Haskell de GTK+. <br />
&nbsp;<br />
Clique pour fermer.&lt;/property&gt; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;property name=&quot;visible&quot;&gt;True&lt;/property&gt; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;property name=&quot;can_focus&quot;&gt;True&lt;/property&gt; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;property name=&quot;receives_default&quot;&gt;True&lt;/property&gt; <br />
&nbsp; &nbsp; &nbsp; &lt;/widget&gt; <br />
&nbsp; &nbsp; &lt;/child&gt; <br />
&nbsp; &lt;/widget&gt; <br />
&lt;/glade-interface&gt;</div></div>
<p>Et voilà, l&rsquo;essentiel est fait.</p>
<p>Voici donc le main.hs, qui est le programme Haskell dont vous avez vu un screenshot plus haut :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">module Main where <br />
&nbsp;<br />
import Graphics.UI.Gtk -- on importe le module GTK <br />
import Graphics.UI.Gtk.Glade -- et le module Glade, pour créer une IHM depuis le XML au format Glade <br />
&nbsp;<br />
main = do <br />
&nbsp; initGUI <br />
&nbsp; Just xml &lt;- xmlNew &quot;test.glade&quot; &nbsp;<br />
&nbsp; window &nbsp; &lt;- xmlGetWidget xml castToWindow &quot;window1&quot; <br />
&nbsp; button &nbsp; &lt;- xmlGetWidget xml castToButton &quot;yo&quot; <br />
&nbsp; onClicked button $ do <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;putStrLn &quot;Bye&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mainQuit <br />
&nbsp; onDestroy window mainQuit <br />
&nbsp; widgetShowAll window <br />
&nbsp; mainGUI</div></div>
<p>Et voilà. Assez simple non ? <img src="https://blog.developpez.com/alp/wp-includes/images/smilies/icon_wink.gif" alt=";)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>La programmation fonctionnelle n&#8217;est pas un jouet académique</title>
		<link>https://blog.developpez.com/alp/p7319/programmation-fonctionnelle/la_programmation_fonctionnelle_n_est_pas</link>
		<comments>https://blog.developpez.com/alp/p7319/programmation-fonctionnelle/la_programmation_fonctionnelle_n_est_pas#comments</comments>
		<pubDate>Fri, 06 Mar 2009 05:27:28 +0000</pubDate>
		<dc:creator><![CDATA[Alp]]></dc:creator>
				<category><![CDATA[Programmation Fonctionnelle]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Bonjour, Je souhaitais écrire un billet à propos de la programmation fonctionnelle, ce sera chose faite. Cela fait maintenant plus de 6 mois que j&#8217;apprends et pratique la programmation fonctionnelle, aussi bien sur le point de vue théorique en m&#8217;intéressant à ses relations avec la théorie des catégories (mathématiques) entre autres, que sur le point de vue pratique, c&#8217;est à dire que j&#8217;ai mené quelques projets (de petite envergure&#8230; oui, c&#8217;est proportionnel au temps que [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Bonjour,</p>
<p>Je souhaitais écrire un billet à propos de la programmation fonctionnelle, ce sera chose faite.</p>
<p>
Cela fait maintenant plus de 6 mois que j&rsquo;apprends et pratique la programmation fonctionnelle, aussi bien sur le point de vue théorique en m&rsquo;intéressant à ses relations avec la théorie des catégories (mathématiques) entre autres, que sur le point de vue pratique, c&rsquo;est à dire que j&rsquo;ai mené quelques projets (de petite envergure&#8230; oui, c&rsquo;est proportionnel au temps que je peux passer dessus) à bien.</p>
<p>Quand on dit &laquo;&nbsp;langage fonctionnel&nbsp;&raquo; ou &laquo;&nbsp;programmation fonctionnelle&nbsp;&raquo;, les gens s&rsquo;imaginent (pour ceux qui ne connaissent pas) des programmes avec tout un tas de fonctions, c&rsquo;est tout. Ce n&rsquo;est pas ça la programmation fonctionnelle. Enfin biensûr il y a des fonctions, mais la programmation fonctionnelle ne s&rsquo;arrête pas là.</p>
<p>Déjà, la programmation fonctionnelle, c&rsquo;est une toute autre façon de concevoir des programmes. Détailler toutes les différences avec la programmation impérative serait pire que les 12 travaux d&rsquo;Hercules et c&rsquo;est pourquoi je ne le ferai pas. Je vais toutefois vous parler des points qui font que je suis désormais adepte de ce style de programmation.</p>
<p><center><img src="http://www.geocities.com/EnchantedForest/1110/images/lambda.gif" alt="" title="La programmation fonctionnelle tire ses racines du lambda-calcul" /></center></p>
<p><span id="more-41"></span></p>
<p>Tout d&rsquo;abord, étant assez orienté mathématiques, il y a une première chose qui me plaît. Dans les langages de programmation fonctionnelle (du moins la plupart), on définit des types, des opérations sur ces types, le tout très simplement et de manière on ne peut plus cohérente.</p>
<p>Ensuite, pour les langages fonctionnels compilés et typés statiquement, on est généralement accompagné d&rsquo;un compilateur très strict, qui tentera d&rsquo;éliminer un maximum d&rsquo;incohérences (comprendre &laquo;&nbsp;erreurs&nbsp;&raquo;) en nous envoyant des erreurs très précises en rapport avec le fait que nous n&rsquo;avons pas bien typé des parties de notre programme. De plus, les 3 langages majeurs pour une utilisation &laquo;&nbsp;real world&nbsp;&raquo;, Haskell, OCaml et F#, ont vu leur compilateur se doter de l&rsquo;inférence de type ; il s&rsquo;agit de la capacité qu&rsquo;a un compilateur a donner lui-même un type à vos valeurs dans le programme (fonctions, expressions, &#8230;). Entre ceci et la vérification des types, la compilation possède une part de travail autour des types en action dans votre code.</p>
<p>De plus, en programmation fonctionnelle, il s&rsquo;agit de ne pas avoir ce que l&rsquo;on appelle des effets de bords ; on parle de programmation fonctionnelle pure ; dans un tel cadre, une fonction à qui l&rsquo;on donne les mêmes entrées renverra toujours la même sortie. Les programmeurs fonctionnels font en sorte d&rsquo;isoler les parties pour lesquelles ce n&rsquo;est pas vrai (lecture d&rsquo;un fichier, intéraction réseau, &#8230;) : monades en Haskell, on laisse la possibilité de faire de l&rsquo;impératif pour OCaml et F#, &#8230; </p>
<p>Continuons sur la curryfication. Cette dernière consiste à faire par exemple d&rsquo;une fonction de 2 arguments 2 fonctions à 1 argument, qui pourront s&rsquo;appliquer partiellement. Si l&rsquo;on définit une fonction &laquo;&nbsp;add&nbsp;&raquo; pour ajouter 2 nombres x et y, alors on pourra appliquer add à son premier argument, x, en lui donnant par exemple la valeur 12, pour obtenir une fonction à UN SEUL argument qui additionnera son argument à 12.</p>
<p>Les fonctions sont capitales en programmation fonctionnelle. Contrairement à dans un certain nombre de langages (beaucoup), les fonctions peuvent être stockées, passées en argument, construites à la volée, retournées par d&rsquo;autres fonctions, etc. Elles deviennent des valeurs de première classe. </p>
<p>A propos du passage en argument, une chose très importante en programmation fonctionnelle est la possibilité d&rsquo;abstraire une partie des algorithmes et d&rsquo;en confier la responsabilité à une fonction donnée en argument par exemple. Une fonction qui prend une autre fonction en argument est appelée &laquo;&nbsp;fonction d&rsquo;ordre supérieur&nbsp;&raquo;. Cela permet de factoriser un maximum de code tout en laissant la variabilité possible grâce au passage de fonction en argument. Le compilateur fera les vérifications nécessaires pour voir si les types concordent, ne vous inquiétez pas.</p>
<p>La paresse est également quelque chose qui s&rsquo;avère bien sympathique parfois. Il s&rsquo;agit de n&rsquo;évaluer une expression qu&rsquo;au moment où l&rsquo;on en aura besoin (affichage du résultat de l&rsquo;évaluation de l&rsquo;expression &#8212; comme une addition &#8212; par exemple). Elle est mise en oeuvre différemment selon les langages (implicitement en Haskell, c&rsquo;est le compilateur qui gère cela, alors que c&rsquo;est explicit en OCaml &#8212; module Lazy).</p>
<p>Tout cela, rajouté aux syntaxes assez simples, donne une très grande expressivité aux langages fonctionnels, proche de l&rsquo;expressivité que l&rsquo;on a en mathématiques. Qui plus est, rappelons-le, les langages fonctionnels sont des langages dits &laquo;&nbsp;déclaratifs&nbsp;&raquo;. On exprime le problème, on obtient la solution, contrairement à ce que l&rsquo;on fait dans un langage impératif où l&rsquo;on doit donner toutes les étapes à la main nous-mêmes.</p>
<p>Bref, beaucoup d&rsquo;avantages, un tout nouveau style de programmation, cela ne vaut-il pas le détour ? Allez, si vous voulez en savoir plus, voici quelques liens essentiels pour terminer ce billet sur la programmation fonctionnelle.<br />
<a href="http://www.developpez.net/forums/f512/autres-langages/langages-fonctionnels/">Forums sur les langages fonctionnels</a><br />
<a href="http://damien-guichard.developpez.com/tutoriels/ocaml/">Cours d&rsquo;introduction à OCaml de Damien Guichard</a> &#8212; dont je me suis beaucoup servi et que j&rsquo;apprécie beaucoup<br />
<a href="http://gorgonite.developpez.com/livres/traductions/haskell/gentle-haskell/">Traduction de &laquo;&nbsp;A gentle introduction to Haskell&nbsp;&raquo;</a> &#8212; un peu rude pour débuter, mais vous fera comprendre pas mal de choses. </p>
<p>N&rsquo;hésitez pas à utiliser le forum pour donner vos avis et retours d&rsquo;expérience ou pour des questions, bien évidemment !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
