<div dir="ltr">Le 26 mars 2014 19:58, Alp Mestanogullari <span dir="ltr"><<a href="mailto:alpmestan@gmail.com" target="_blank">alpmestan@gmail.com</a>></span> a écrit :<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">Ok, je vais essayer de reprendre plus tranquillou ce que j'ai dit en répondant point par point.<br>
<br><div class="gmail_quote">2014-03-26 19:32 GMT+01:00 Gautier DI FOLCO <span dir="ltr"><<a href="mailto:gautier.difolco@gmail.com" target="_blank">gautier.difolco@gmail.com</a>></span>:<div class=""><br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">Le 26 mars 2014 17:55, Alp Mestanogullari <span dir="ltr"><<a href="mailto:alpmestan@gmail.com" target="_blank">alpmestan@gmail.com</a>></span> a écrit :<div>


<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Le truc du contexte, je pense qu'ya une bonne image pour le représenter.<div><br></div><div>Ce qui est propre au monade et que n'ont pas les applicatives, c'est que la suite d'une fonction dépende de ce qui se passe à un moment donné.</div>





<div>Exemple:</div><div><br></div><div>foo :: IO ()</div><div>foo = do</div><div>  s <- getLine</div><div>  case s of</div><div>      "hello" -> putStrLn " world!"</div>

<div>      _        -> foo</div><div><br></div><div>ici, on fait quelque chose dans IO, et selon le résultat, il peut se passer deux choses complètement différentes. On se sert beucoup de ce genre de "contexte" dans les parsers par exemple, c'est littéralement explicit, les parsers ont une forte analogie avec la monade State.</div>



</div></blockquote><div><br></div></div><div>En gros tu crée une dépendance qui force ton exécution dans un certain ordre en lui passant le précédent monde ?<br></div></div></div></div></blockquote><div><br></div></div><div>


Bah, tu as tout simplement le moyen de faire ça avec ce que te donne IO. Mais tu pourrais faire pareil dans une autre monade.</div><div>L'idée c'est que là, 'getLine' c'est de type IO String, donc 's' est une String, on est d'accord? Hé bien on peut grâce à la do-notation (c'est grâce à la façon dont la do-notation est traduite en avalanche de >>= et return & compagnie en fait). Comment?</div>


<div><br></div><div>Très simple:</div><div><br></div><div>f :: IO ()</div><div class=""><div>f = do</div><div>  s <- getLine</div></div><div>  putStrLn s</div><div><br></div><div>se traduit en</div>

<div><br></div><div>f' :: IO</div><div>f' = getLine >>= \s -> putStrLn s</div><div><br></div><div>-- ou plus simple: f' = getLine >>= putStrLn</div></div></div></div></blockquote><div><br></div>
<div>Je viens de piger je crois.<br></div><div>En fait je me mélangeais dans le sésucrage, c'est plus claire déjà.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>
</div>
<div>Re-regardons le type de >>= pour IO:</div><div><br></div><div>(>>=) :: IO a -> (a -> IO b) -> IO b</div><div><br></div><div>En gros t'as qqch qui va te produire un 'a' à travers des effets (lecture de fichiers, depuis une DB, depuis stdin, ...) - (c'est ça la signification de 'IO a') - et tu vois que le deuxième argument de >>= prend un 'a', donc en gros >>= donne à son deuxième argument la valeur générée par le premier argument. C'est cette "inspection" qui te permet en gros de faire un peu ce que tu veux avec ce 'a' tant que tu produis un 'IO b' pour un certain type 'b'.</div>
</div></div></div></blockquote><div><br></div><div>ça c'était bon (je suis fier de moi alors que c'est "tout bête")<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div class="">

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



<div dir="ltr">

<div></div><div>Alors qu'avec Applicative, tu peux avoir des "effets", des computations avec un petit truc en plus (parseurs qui retournent une valeur mais qui entre temps ont consumé une partie de l'input pour produire ces valeurs), etc, mais t'es obligé de garder la même "structure" pour ton code, ex:</div>



</div></blockquote><div><br></div></div><div>Tu entends quoi par "computation" (désolé, je bloque sur ce terme, ça ne rentre pas :/)<br></div></div></div></div></blockquote><div><br></div></div><div>l'évaluation d'une expression, de qqch.</div>
</div></div></div></blockquote><div><br></div><div>pas mieux, ça correspond à quoi ?<br></div><div> <br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">
<div class="gmail_extra"><div class="gmail_quote"><div class="">

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div>Tu veux dire truc en moins ou Monade ? si non, je sur largué.<br>


</div></div></div></div></blockquote><div><br></div></div><div>Non non, je veux dire que Monad permet ça aussi, mais Applicative ne permet *QUE* ça, alors que Monad, comme montré juste au-dessus, permet d'inspecter ce que t'as produit et réagir en conséquence. Applicative te permet juste d'appliquer des fonctions pures, par ex de type 'a -> b -> c', à des arguments qui viennent "d'ailleurs", par ex 'IO a' et 'IO b'.</div>


<div><br></div><div>Exemple:</div><div><br></div><div>data ProgrammingLanguage = ProgrammingLanguage { name :: String, fileExtension :: String }</div><div><br></div><div>getProgrammingLanguageFromStdin :: IO ProgrammingLanguage</div>


<div>getProgrammingLanguageFromStdin =</div><div>    ProgrammingLanguage <$> getLine</div><div>                                      <*> getLine</div><div><br></div><div>Ca va te permettre d'entrer le nom d'un langage, <ENTER>, l'extension des fichiers associée à ce langage (".hs" pour Haskell par exemple, quoi), et ça te retournera une valeur de type ProgrammingLanguage.</div>


<div><br></div><div>Si tu utilisais les fonctions de Monad pour faire ça:</div><div><br></div><div>getProgrammingLanguageFromStdin :: IO ProgrammingLanguage</div><div>getProgrammingLanguageFromStdin = do</div>

<div>    name  <- getLine</div><div>    fileExt <- getLine</div><div>    return $ ProgrammingLanguage name fileExt</div><div><br></div><div>Tu noteras que contrairement à mon exemple à la con de 'case s of "hello" -> ...', ici on cherche pas à agir différemment selon la valeur qu'on obtient grâce à getLine, que ce soit pour le nom où l'extension, et c'est exactement ce qui fait qu'on peut écrire cette fonction tout à fait utile aussi bien avec les fonctions d'Applicative ( <*> combinée à <$> = fmap de Functor ) qu'avec la do-notation.</div>
</div></div></div></blockquote><div><br></div><div>ok pigé, je ne voyais pas où tu voulais en venir avant (je pensais que tu parlais de faire des IO via des Applicatives).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">

<div></div><div>Histoire d'être complet, si tu veux écrire ça sans le do mais quand même avec les fonctions de Monad:</div><div><br></div><div>getProgrammingLanguageFromStdin :: IO ProgrammingLanguage</div>

<div>getProgrammingLanguageFromStdin =</div><div>    getLine >>= \name -> getLine >>= \fileExt -> return (ProgrammingLanguage name fileExt)</div><div class=""><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Perdu :/<br></div><div>Quelle est la "déclaration" (je ne sais pas comment ça se dit : data/type/newtype) de Parser ?<br></div></div></div></div>


</blockquote><div><br></div></div><div>Peu importe, mais il est établi que les parseurs sont Monad/Applicative. "Parser Int" c'est qqch qui va essayer de parser un int quand tu lui donneras une String sur laquelle essayer.</div>


<div><br></div><div>Parser Person c'est un truc qui va essayer de parser une "Person" quand tu lui donneras une entrée sur laquelle essayer. Comment? Il va essayer de parser un Int, puis une String, et si les deux réussissent, il passe tout ça au constructeur 'Person'.</div>
<div class="">

<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div>Comment le monde est "passé" aux parse* ?<br>


</div></div></div></div></blockquote><div><br></div></div><div>Ca fait partie du fonctionnement interne. Généralement un parseur c'est une fonction du genre 'String -> (a, String)'. Donc un truc qui attend une String en entrée et qui va tenter de produire un 'a' (Person par exemple dans notre exemple) grâce à ce qu'il trouvera dans cette String et retournera à côté de la valeur "ce qui n'a pas encore été consommé". Dans la vraie vie, ils sont plus compliqués, mais ça te donne peut-être une idée.</div>
</div></div></div></blockquote><div><br></div><div>ok, compris.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">
<div class="gmail_quote"><div class="">

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>
</div><div>Comment il sait quel type de Parser il doit produire ? (le première ligne du corps de blah appel le Constructeur du type Parser, comment sait-il qu'il va "retourner" une valeur de type Parser Person ? vu que Person n'est indiqué nul part dans le corps).<br>


</div></div></div></div></blockquote><div><br></div></div><div>Il le sait parce que il connait le type des attributs de Person (age de type Int, name de type String) et il connait le type de parseInt et parseString.</div>


<div>Et si, justement, Person est indiqué dans le corps. La version Monad t'aidera peut-être:</div><div><br></div><div>parsePerson :: Parser Person</div><div>parsePerson = do</div><div>    age    <- parseInt</div>


<div>    name <- parseString</div><div>    return (Person age name)</div><div><br></div><div>La version applicative fait *EXACTEMENT* ça.</div></div></div></div></blockquote><div><br></div><div>ok, je comprends.<br></div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Ne t'inquiètes pas, on est tous passés par là, faut changer sa façon de penser pour bien piger tout ça. Faut oublier toutes les merdes qu'on a appris ailleurs, repenser la programmation. Ca va prendre un peu de temps mais tu vas y arriver.</div>


<div><br></div><div>En attendant, hésite pas à signaler ce qui n'est toujours pas clair après ce message.</div></div></div></div></blockquote></div><br></div><div class="gmail_extra">Merci, merci encore, c'est ça que j'aime bien en Haskell, dès que tu as compris c'est limpide mais tu as toujours des choses à apprendre.<br>
</div></div>