• [^] # Re: Méconnaissance

    Posté par . En réponse au journal Compilateur et Monad Reader. Évalué à 2.

    J'ai toujours le sentiment que, comme te l'a écrit Drup, tu forces des idiomes haskellien en OCaml :

    Et tu ne t'es dit a aucun moment que peut être, juste peut être, tu essayais de forcer les idiomes haskell en OCaml ?

    La monade reader est un artifice Haskellien pour palier aux restrictions sur les effets de bords. Elle ne sert rigoureusement a rien en caml.

    Les monades sont nécessaires en Haskell, entre autre, parce qu'il n'y a pas de paradigme impératif dans ce langage; en OCaml cet usage est inutile. Si tes fonctions ont une sortie de type unit, alors chaîne les avec le point-virgule ;. Tu peux toujours les encadrés dans un bloc begin ... end, si tu veux visualiser cette structure de bloc d'enchaînement de procédure.

    Ensuite, multiplier les fonctions anonymes à tout va, c'est laid et cela rend le code difficilement compréhensible. Je préfère l'usage du let ... in pour les définitions locales, ou dans les cas étudiés dans ton article les lambda sont inutiles : réutiliser le nom de la fonction prédéfinie (ce qui s'étend aux applications partielles). Les lambda (ou dans ma préférence les let ... in) n'ont d'intérêt que si la définition est « complexe », c'est pour cela que dans les exemples de ton journal elles ne servaient à rien.

    Enfin, j'exprime, ici, non le point de vue d'une programmeur-développeur en OCaml, mais celui d'un mathématicien-logicien. Lorsque je lis du code OCaml, je le fais à travers le prisme de la correspondance de Curry-Howard (ou correspondance preuve-programme). Du code, de ce point de vue, n'est rien d'autre que la preuve d'un énoncé (les types OCalm sont un sous-ensemble de la logique propositionnelle du second ordre). Une fonction est un énoncé qui prend des prémisses d'un certain type et renvoie une conclusion d'un certain type.

    De ce point de vue, les fonctions locales (ou lambda fonctions, fonctions anonymes...) sont l'analogue des lemmes : leur donner un nom, par l'intermédiaire d'un let ... in, ou en les définissant dans l'espace de nom du module, permet au lecteur d'en comprendre plus aisément la signification.
    Si son rôle est celui d'un statut de lemme, il n'est pas nécessaire de l'exporter dans l'interface du module, interface qui ne présentera que les propositions et théorèmes importants qu'il contient.
    Ainsi, l'approche fonctionnelle par composition des opérateurs permet de mieux appréhender les raisonnements effectuer par le développeur, et de raisonner sur le code lui-même.

    Le problème n'est pas de résoudre ce que tu as exprimé ainsi :

    (* 
     * sans la notation infixe on perd ~ 4 caractères à la louche,
     * quelle victoire !
     *)

    mais de pouvoir comprendre facilement, à la lecture, le raisonnement de l'auteur. Une preuve tout à fait correcte, mais illisible, voire incompréhensible n'est pas d'une grande utilité. Et pour tout te dire, à la lecture de ton journal, j'ai du m'y reprendre à plusieurs fois pour comprendre où tu voulais en venir. ;-)

    Un exemple intéressant, de ce point de vue, est l'article de Gérard Huet sur le zipper. Que ce soit dans la définition de ses structures combinatoires, dans les fonctions qu'il définit (propositions qu'il prouve), les pattern matching comme raisonnement par cas... la lecture du code est limpide. :-)

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.