Derniers messages sur Zeste de Savoirhttps://zestedesavoir.com/forums/2017-02-02T23:30:36+01:00Les derniers messages parus sur le forum de Zeste de Savoir.Compilation de Scheme, message #1401422017-02-02T23:30:36+01:00Eusèbe/@Eus%C3%A8behttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p140142<blockquote>
<p>ce langage est toujours enseigné comme langage de référence</p>
</blockquote>
<p>C’est toujours enseigné parce que ça reste difficilement contournable, mais comme « référence », bof : le langage généraliste à la mode, c’est Java ou Python maintenant. Les formations où le C prend cette place sont soit des formations assez orientées électronique ou embarqué, soit des formations où les gens qui décident des programmes ne sont pas informaticiens et ne connaissent de toute façon rien d’autre que le (mauvais) « C/C++ ».</p>
<blockquote>
<p>je pense qu’il s’agit d’un challenge intéressant </p>
</blockquote>
<p>Pas tellement, en fait. Si c’est pour faire du C, il y a un tas de choses plus intéressantes et instructives, et si c’est pour apprendre la compilation, il y a plein d’autres langages qui rendent la tâche plus intéressante. Devoir se concentrer sur la gestion de la mémoire alors qu’on cherche à écrire un compilateur, donc un programme qui effectue des opérations complexes sur des données riches, c’est contre-productif. Alors bien sûr, ça reste possible, mais ce serait une erreur de penser que « c’est plus dur donc j’apprends plus de choses » à la « ce qui ne me tue pas me rend plus fort ».</p>
<blockquote>
<p>(d’autant plus que bon nombre de compilateurs/VM/interpréteurs pour d’autres langages sont écrits en C).</p>
</blockquote>
<p>Les VM, c’est possible, pour deux raisons : d’une part, le format des entrées est en général particulièrement simple (parce que tout le travail de transformation depuis un langage expressif a été fait par la compilation), d’autre part, c’est un programme qui cherche en général explicitement des hautes performances, et pour lequel on veut souvent toucher un peu aux détails de l’architecture qui exécutera le code. Le C n’est probablement pas le langage le plus adapté pour autant, mais c’est un choix qui se comprend déjà plus. Pour les compilateurs, à part les compilateurs C (parce qu’on veut être auto-suffisant), c’est de plus en plus rare. </p>Compilation de Scheme, message #1401242017-02-02T21:39:01+01:00Lalla/@Lallahttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p140124<p>Oui évidemment, le C n’est pas adapté à l’écriture de compilateurs, on est d’accord. Mais puisque ce langage est toujours enseigné comme langage de référence j’aurais pensé qu’à un moment où à un autre quelqu’un d’autre aurait écrit un compilateur de Scheme en C. Visiblement ça n’est pas le cas et bien que je sois d’accord sur l’aspect pratique, je pense qu’il s’agit d’un challenge intéressant (d’autant plus que bon nombre de compilateurs/VM/interpréteurs pour d’autres langages sont écrits en C).</p>Compilation de Scheme, message #1401152017-02-02T20:04:18+01:00Eusèbe/@Eus%C3%A8behttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p140115<blockquote>
<p>Je dois dire que c’est assez perturbant, surtout que le C est l’un des langages les plus utilisés au monde, il n’y a pas de raison que ça n’existe pas du tout.</p>
</blockquote>
<p>Bof, en 2017 c’est utilisé pour de l’embarqué parce qu’il n’y a pas le choix ou pour des raisons historiques. Pour écrire des compilateurs, c’est particulièrement inadapté.</p>Compilation de Scheme, message #1399652017-01-31T19:13:12+01:00minirop/@minirophttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p139965<figure>
<blockquote>
<p>Suis-je le seul masochiste à vouloir tout faire en C ?</p>
</blockquote>
<figcaption><a href="https://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p139900">Lalla</a></figcaption>
</figure>
<p>Beaucoup de langages essaient d’être auto-suffisant. Et j’ai souvent lu que Scheme était de bons langages pour écrire des compilateurs. Seuls les langages interprétés (Python, ruby, PHP) restent généralement en C-like.</p>Compilation de Scheme, message #1399002017-01-31T11:42:11+01:00Lalla/@Lallahttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p139900<p>Vis à vis du bootstrap, ce qui m’intéresse, c’est pas vraiment le procédé. Je sais ce que c’est et comment m’y prendre. En fait, ce qui m’interpèle c’est que lors que je recherche une implémentation en C d’un langage dérivé de Scheme (ou même d’un Lisp quelconque), je ne trouve jamais un compilateur écrit purement en C et basta. Je finis toujours par avoir un compilateur minimal en C et derrière le vrai compilateur écrit en Scheme. Suis-je le seul masochiste à vouloir tout faire en C ? Je dois dire que c’est assez perturbant, surtout que le C est l’un des langages les plus utilisés au monde, il n’y a pas de raison que ça n’existe pas du tout.</p>
<p>D’accord, je comprends mieux le pourquoi du comment, merci beaucoup. <img alt=":)" src="/static/smileys/smile.png"></p>Compilation de Scheme, message #1398762017-01-31T05:24:21+01:00kelepoc/@kelepochttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p139876<p>Salut.</p>
<p>Un des problèmes du <em>eval</em> est la gestion de l’environnement.
D’abord, il est bon de noter que la norme R5RS ne permet pas au <em>eval</em> d’accéder à l’environnement local. Seul l’environnement global peut être lu (ce <a href="http://stackoverflow.com/a/4999480">post</a> explique pourquoi).
Donc le code que tu montres en exemple est invalide (pour R5R5. Je ne sais pas ce que disent les autres normes, mais c’est surement pareil).</p>
<p>Comme dit Saroupille, tu dois utiliser un système externe pour implémenter le <em>eval</em>.
Tu peux faire appel à un autre compilateur, mais ça peut être difficile parce que tu dois lui transmettre ton environnement global (ça fait un travail, et une dépendance supplémentaire).</p>
<p>L’autre solution est d’embarquer ton propre compilateur/interprète, ça simplifie la gestion de l’environnement. Après tout, c’est ton code donc tu sais comment l’environnement est représenté.</p>
<p>Une autre chose intéressante est que tu peux embarquer ce système uniquement si le programme que tu compiles utilise <em>eval</em>. Dans tous les autres cas, pas besoin de l’intégrer, donc le code généré reste léger.</p>
<p>Pour ta seconde question, non tu peux très bien faire un bootstrap sans utiliser d’autre compilateur ("mini-Scheme" comme tu les appelles).
Dans ce cas tu as deux solutions:</p>
<ol>
<li>Tu conserves et distribues un build de l’ancienne version de ton compilateur qui est utilisé pour construire l’actuelle. Mais conserver un build complet est assez lourd, et si tu génères de l’assembleur (donc le build est en binaire), c’est pas très portable.</li>
<li>Tu écris ton compilateur dans un Scheme standard, et tu utilises un autre compilateur pour construire le tiens. Puis tu utilises la sortie pour compiler à nouveau ton compilateur.
Le problème cette fois est que tu as une dépendance externe (ton compilateur n’est plus auto-suffisant).</li>
</ol>
<p>Donc l’autre solution est d’utiliser un autre petit compilateur qui est très primitif, et pas optimisé (quelques centaines de lignes de code). Tu peux même éviter d’utiliser un GC, eval, les continuations, etc…
Avec ce petit compilateur, tu compiles une version non efficace de ton <em>vrai</em> compilateur.
Puis tu utilises la sortie pour compiler à nouveau ton compilateur pour avoir une version, cette fois, efficace. Et là, tu deviens vraiment auto-suffisant. <img alt=":magicien:" src="/static/smileys/magicien.png"></p>
<p>Donc non tu n’est pas obligé d’utiliser un second petit compilateur, mais c’est bien plus satisfaisant <img alt=":D" src="/static/smileys/heureux.png"></p>Compilation de Scheme, message #1398022017-01-29T17:45:02+01:00Lalla/@Lallahttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p139802<p>Je vois ! Donc typiquement il faudrait que je fasse une bibliothèque de mon compilateur (et un programme qui l’utilise pour compiler des fichiers, ça tombe sous le sens) et que je lie chaque programme contenant un eval à celui-ci ?</p>Compilation de Scheme, message #1397192017-01-28T15:02:34+01:00Saroupille/@Saroupillehttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p139719<p>Lorsque tu compiles un <code>eval</code>, ton compilateur doit avoir accès à un autre compilateur, en l’occurence cela pourrait être le tiens. Et ensuite tu balances le code au compilateur, etc…</p>Compilation de Scheme, message #1396892017-01-28T10:13:07+01:00Lalla/@Lallahttps://zestedesavoir.com/forums/sujet/7877/compilation-de-scheme/?page=1#p139689<p>Bonjour les copains/copines,</p>
<p>je travaille actuellement sur une projet de compilateur pour un langage très fortement inspiré de Scheme écrit en C89 (pour le plaisir/pleurer un bon coup). Autant j’ai une idée assez précise de comment tout va se goupiller, autant je suis assez perdu concernant l’expansion des macros et de la "fonction" <code>eval</code>.</p>
<p>En effet, même si je remplace un appel à une macro par son corps (moyennant des ajustements avec les <em>quotations</em>), je ne vois pas comment je peux compiler un appel à <code>eval</code> puisque celle-ci peut nécessiter des informations disponibles uniquement au <em>runtime</em>. Par exemple, dans le code suivant, mes deux premières lignes de codes devraient être équivalentes, mais à cause du <code>eval</code>, je devrais connaître la valeur de f à la compilation, ce qui n’est pas garanti, comme montré dans le bout de code juste après.</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="p">(</span><span class="nb">eval </span><span class="p">(</span><span class="nb">list </span><span class="ss">'f</span> <span class="mi">5</span><span class="p">))</span>
<span class="p">(</span><span class="nf">f</span> <span class="mi">5</span><span class="p">)</span>
<span class="c1">;; Certes personne ne devrait écrire ça, mais ça illustre bien ce que je veux dire.</span>
<span class="p">(</span><span class="k">let </span><span class="p">((</span><span class="nf">function-name</span> <span class="p">(</span><span class="nf">readline</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">eval </span><span class="p">(</span><span class="nb">list </span><span class="p">(</span><span class="nb">string->symbol </span><span class="nv">function-name</span><span class="p">)</span> <span class="mi">5</span><span class="p">)))</span>
</pre></div>
</td></tr></table></div>
<p>J’aurais donc voulu savoir comment régler ce problème, s’il y a une technique bien connue/définie pour compiler cette fonctionnalité du Scheme.</p>
<p>Par ailleurs, question annexe, j’ai cherché d’autres compilateurs de Scheme écrits en C pour voir comment d’autres font et je ne tombe que sur des compilateurs de "mini-Scheme" servant à bootstrap le vrai compilateur. Est-ce finalement obligé ou est-ce ainsi parce que le Scheme est quand-même bien plus agréable que le C écrire un compilateur ? Si, par hasard, vous connaissez un compilateur de Scheme écrit en C (uniquement en C) qui puisse me servir d’inspiration, il serait gentil de me mettre dans le coup <img alt=":)" src="/static/smileys/smile.png"></p>
<p>Merci beaucoup pour votre lecture et de vos éventuelles réponses.<br>
Lalla.</p>Evaluation d'expressions & gestion des types, message #474982015-03-11T22:41:40+01:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p47498<p>Effectivement, tu perds ici l'intérêt du constructeur Add unique, et tant qu'à partir comme ça, autant avoir deux types classiques int_exp et float_exp. Par ailleurs, il me semble que c'est un problème orthogonal au <code>final</code> : ici tu résous juste le choix de l'opérateur pour additionner, que ma solution plus haut règle en gardant le tag ont/float pour les expressions évaluées.</p>Evaluation d'expressions & gestion des types, message #474442015-03-11T18:46:04+01:00olzd/@olzdhttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p47444<p>Ta solution est intéressante, j'aurais jamais pensé à introduire les types <code>final</code> et <code>non_final</code>.
Après je suis d'accord que convertir en <code>float</code> n'est pas du tout satisfaisant comme solution. En fait, j'étais arrivé à un truc comme ça;</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="o">_</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">:</span> <span class="kt">int</span> <span class="n">exp</span> <span class="o">*</span> <span class="kt">int</span> <span class="n">exp</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">FAdd</span> <span class="o">:</span> <span class="kt">float</span> <span class="n">exp</span> <span class="o">*</span> <span class="kt">float</span> <span class="n">exp</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">exp</span>
</pre></div>
</td></tr></table>
<p>Du coup ça règle le problème mais je duplique mes constructeurs.</p>Evaluation d'expressions & gestion des types, message #474072015-03-11T14:11:21+01:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p47407<blockquote>
<blockquote>
<p>Bon, je m'y attendais un peu mais du coup je dois faire un truc du genre:</p>
<p><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">IntSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">int</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="k">module</span> <span class="nc">FloatSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">float</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="c">(* ... *)</span>
</pre></div>
</td></tr></table>
</p>
</blockquote>
<p>Je ne sais pas si c'est ce que tu voulais mais ici, on est d'accord que tu vas comparer par exemple <code>Value.Int 0</code> avec <code>Value.Int 2</code> et non <code>0</code> avec <code>2</code> ? Bon, <code>Pervasives.compare</code> semble «bien» se comporter de ce point de vue là en testant rapidement donc admettons (pas trouvé de source qui explique comment <code>Pervasives.compare</code> se comporte avec les constructeurs, avec une recherche rapide).</p>
</blockquote>
<p>Si je ne dis pas de bêtise, un constructeur défini avant un autre est considéré comme inférieur, et en cas de constructeur identique on compare les paramètres avec une sorte d'ordre lexicographique. Ce qu'il faut retenir, c'est qu'en pratique c'est relativement utilisable quand on sait qu'on n'a pas besoin d'un comportement précis mais juste d'une fonction de comparaison qui marche (par exemple pour mettre dans un <code>Set</code>), mais que si on veut faire les choses de façon propre c'est effectivement une bonne idée de la définir soi-même (ou d'utiliser <a href="https://github.com/whitequark/ppx_deriving">ppx_deriving</a> pour l'avoir pour pas cher).</p>
<blockquote>
<blockquote>
<p>Mais ça m'oblige à écrire:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">Exp</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">type</span> <span class="o">_</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">ISet</span> <span class="o">:</span> <span class="kt">int</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span> <span class="kt">list</span> <span class="o">-></span> <span class="nn">IntSet</span><span class="p">.</span><span class="n">t</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">FSet</span> <span class="o">:</span> <span class="kt">float</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span> <span class="kt">list</span> <span class="o">-></span> <span class="nn">FloatSet</span><span class="p">.</span><span class="n">t</span> <span class="n">t</span>
<span class="c">(* ... *)</span>
<span class="k">end</span>
</pre></div>
</td></tr></table>
<p>D'ailleurs je trouve étrange de pouvoir écrire <code>Exp.ISet [Value.Int 1; Value.Int 2]</code> et de voir que j'ai <code>IntSet.t Exp.t</code> comme type puisque je ne manipule pas vraiment de Set là.</p>
</blockquote>
<p>Le type utilisé pour décorer <code>t</code> dans <code>Exp</code> est juste un «tag». Ça ne veut pas dire que tu as une valeur du type en question. La valeur que tu obtiens est bien du type <code>IntSet.t Exp.t</code> mais le fait que ce soit <code>IntSet.t</code> à cette position dit juste qu'elle a été construite avec le constructeur <code>ISet</code> plutôt que le constructeur <code>FSet</code>. Du coup, je ne pense pas que c'était ce que tu voulais faire.</p>
</blockquote>
<p>Le nom habituellement utilisé est « type fantôme » : c'est effectivement un paramètre de type qui ne correspond à aucun paramètre des valeurs de ton type <code>exp</code>, mais qui sert à faire vérifier au typeur certaines propriétés. Tu peux lire <a href="https://blogs.janestreet.com/howto-static-access-control-using-phantom-types/">ça</a> (c'est assez bien fait) ou chercher « type fantôme ocaml ».</p>
<blockquote>
<p>D'ailleurs je suis tombé sur un autre truc gênant:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8
9</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="o">_</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">:</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">*</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">-></span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="n">exp</span> <span class="o">-></span> <span class="n">a</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span><span class="n">y</span><span class="o">)</span> <span class="o">-></span> <span class="c">(* (eval x) + (eval y) ou (eval x) +. (eval y) *)</span>
</pre></div>
</td></tr></table>
<p>Et là, c'est vraiment chiant. Une solution serait de tout convertir en <code>float</code>.</p>
</blockquote>
<p>Une solution serait d'écrire :</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="n">final</span>
<span class="k">type</span> <span class="n">non_final</span>
<span class="k">type</span> <span class="o">(_,</span> <span class="o">_)</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="o">(</span><span class="kt">int</span><span class="o">,</span> <span class="n">final</span><span class="o">)</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="o">(</span><span class="kt">float</span><span class="o">,</span> <span class="n">final</span><span class="o">)</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">:</span> <span class="o">(</span><span class="k">'</span><span class="n">a</span><span class="o">,</span> <span class="k">'</span><span class="n">b</span><span class="o">)</span> <span class="n">exp</span> <span class="o">*</span> <span class="o">(</span><span class="k">'</span><span class="n">a</span><span class="o">,</span> <span class="k">'</span><span class="n">c</span><span class="o">)</span> <span class="n">exp</span> <span class="o">-></span> <span class="o">(</span><span class="k">'</span><span class="n">a</span><span class="o">,</span> <span class="n">non_final</span><span class="o">)</span> <span class="n">exp</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span> <span class="n">b</span><span class="o">.</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="n">exp</span> <span class="o">-></span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">final</span><span class="o">)</span> <span class="n">exp</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">x</span> <span class="o">-></span> <span class="nc">Int</span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">x</span> <span class="o">-></span> <span class="nc">Float</span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span> <span class="n">y</span><span class="o">)</span> <span class="o">-></span>
<span class="k">begin</span> <span class="k">match</span> <span class="n">eval</span> <span class="n">x</span><span class="o">,</span> <span class="n">eval</span> <span class="n">y</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">x'</span><span class="o">,</span> <span class="nc">Int</span> <span class="n">y'</span> <span class="o">-></span> <span class="nc">Int</span> <span class="o">(</span><span class="n">x'</span> <span class="o">+</span> <span class="n">y'</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">x'</span><span class="o">,</span> <span class="nc">Float</span> <span class="n">y'</span> <span class="o">-></span> <span class="nc">Float</span> <span class="o">(</span><span class="n">x'</span> <span class="o">+.</span> <span class="n">y'</span><span class="o">)</span>
<span class="k">end</span>
<span class="k">let</span> <span class="n">full_eval</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="k">'</span><span class="n">b</span><span class="o">)</span> <span class="n">exp</span> <span class="o">-></span> <span class="n">a</span> <span class="o">=</span> <span class="k">function</span> <span class="n">x</span> <span class="o">-></span>
<span class="k">match</span> <span class="n">eval</span> <span class="n">x</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span>
</pre></div>
</td></tr></table>
<p>Tu remarqueras que j'ai utilisé un autre type fantôme qui indique si une expression est pleinement évaluée ou pas, ce qui me permet de ne pas avoir de warning sans avoir traité les motifs <code>Int _, Add (_, _)</code>. Tu remarqueras aussi que le type a encore grossi : les GADT, c'est quelque chose de très rigolo et d'assez puissant, mais dans des programmes réels, il faut bien peser leur utilisation pour ne pas se retrouver avec des types énormes pour des vérifications dont on n'a pas besoin. Cela dit, ici on a un joli exemple de ce qu'on peut faire avec, donc si ça n'est pas trop pénible à utiliser dans le reste de ton code, ce serait dommage de s'en priver.</p>
<p>Mais dans tous les cas, ici tu n'as surtout pas envie de tout convertir en float : c'est tentant dans ce cas particulier parce qu'on a envie de dire que « int c'est des entiers et float des réels, et un entier ça peut bien être un réel », mais d'une part ce n'est pas tout à fait vrai, d'autre part tu pourrais vouloir avoir d'autres types complètement différents dans ton arbre (par exemple des <code>string</code>, et l'addition serait la concaténation), et ça n'est pas très satisfaisant de se dire que ça ne marche que parce qu'en agitant un peu les mains on peut faire semblant qu'un int c'est un float. Tout le principe de cette discussion est d'arriver à faire la différence proprement entre une expression entière et une expression flottante, après tout.</p>
<p>Note PS : dans le code que je t'ai donné, il n'est pas nécessaire de spécifier dans le type que <code>Int</code> et <code>Float</code> sont <code>final</code>. Par contre il est nécessaire de garder tout le reste, et notamment la définition d'un type <code>final</code>, pour dire que <code>eval</code> renvoie une expression d'un type différent de celui de <code>Add (_, _)</code>. Et l'annotation <code>type b.</code> devient alors nécessaire pour une autre raison : dans le code ci-dessus, elle indique au typeur qu'il s'agit d'une récursion polymorphe, et là elle deviendrait nécessaire à cause des GADT. Ce sont des détails que je ne connais que superficiellement, et il est possible que la deuxième raison soit en fait aussi vraie dans le premier cas.</p>Evaluation d'expressions & gestion des types, message #473932015-03-11T13:43:24+01:00olzd/@olzdhttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p47393<p>Salut,</p>
<blockquote>
<p>Le type utilisé pour décorer t dans Exp est juste un «tag». Ça ne veut pas dire que tu as une valeur du type en question. La valeur que tu obtiens est bien du type IntSet.t Exp.t mais le fait que ce soit IntSet.t à cette position dit juste qu'elle a été construite avec le constructeur ISet plutôt que le constructeur FSet. Du coup, je ne pense pas que c'était ce que tu voulais faire.</p>
</blockquote>
<p>Ok, j'avais pas vraiment compris que c'était juste un tag. Par contre avec ta solution il faut réécrire les fonctions add, mem… Après je vois pas trop comment éviter ça.</p>
<p>D'ailleurs je suis tombé sur un autre truc gênant:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8
9</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="o">_</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">:</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">*</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">-></span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="n">exp</span> <span class="o">-></span> <span class="n">a</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span><span class="n">y</span><span class="o">)</span> <span class="o">-></span> <span class="c">(* (eval x) + (eval y) ou (eval x) +. (eval y) *)</span>
</pre></div>
</td></tr></table>
<p>Et là, c'est vraiment chiant. Une solution serait de tout convertir en <code>float</code>.</p>Evaluation d'expressions & gestion des types, message #473702015-03-11T09:03:16+01:00dentuk/@dentukhttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p47370<p>Salut,</p>
<p>J'ai pas énormément d'expérience avec les GADTs mais comme tu n'as plus beaucoup de réponses je vais tenter ma chance.</p>
<blockquote>
<p>J'ai commencé à jouer avec les GADTs mais j'ai un problème:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">Value</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">type</span> <span class="o">_</span> <span class="n">t</span> <span class="o">=</span> <span class="c">(* ... *)</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="n">t</span> <span class="o">-></span> <span class="n">a</span> <span class="n">t</span> <span class="o">-></span> <span class="kt">int</span> <span class="o">=</span> <span class="c">(* ... *)</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nc">ValueSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="nc">Value</span><span class="o">)</span>
</pre></div>
</td></tr></table>
<p>J'ai ça comme erreur:</p>
<p><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8</pre></div></td><td class="code"><div class="codehilite"><pre>Error: Signature mismatch:
...
Type declarations do not match:
type 'a t = (* ... *)
is not included in
type t
File "ast2.ml", line 2, characters 7-127: Actual declaration
They have different arities.
</pre></div>
</td></tr></table>
</p>
</blockquote>
<p>Ça me semble effectivement normal, la signature demande ici un type sans paramètre. D'ailleurs, si on pouvait faire ce que tu as écris, la signature de <code>add</code> permettrait a priori d'ajouter d'abord une valeur construite avec <code>Float</code>, puis une autre construite avec <code>Int</code>, or ta fonction de comparaison ne sait pas traiter deux valeurs construites avec un constructeur différent.</p>
<blockquote>
<p>Bon, je m'y attendais un peu mais du coup je dois faire un truc du genre:</p>
<p><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">IntSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">int</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="k">module</span> <span class="nc">FloatSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">float</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="c">(* ... *)</span>
</pre></div>
</td></tr></table>
</p>
</blockquote>
<p>Je ne sais pas si c'est ce que tu voulais mais ici, on est d'accord que tu vas comparer par exemple <code>Value.Int 0</code> avec <code>Value.Int 2</code> et non <code>0</code> avec <code>2</code> ? Bon, <code>Pervasives.compare</code> semble «bien» se comporter de ce point de vue là en testant rapidement donc admettons (pas trouvé de source qui explique comment <code>Pervasives.compare</code> se comporte avec les constructeurs, avec une recherche rapide).</p>
<blockquote>
<p>Mais ça m'oblige à écrire:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">Exp</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">type</span> <span class="o">_</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">ISet</span> <span class="o">:</span> <span class="kt">int</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span> <span class="kt">list</span> <span class="o">-></span> <span class="nn">IntSet</span><span class="p">.</span><span class="n">t</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">FSet</span> <span class="o">:</span> <span class="kt">float</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span> <span class="kt">list</span> <span class="o">-></span> <span class="nn">FloatSet</span><span class="p">.</span><span class="n">t</span> <span class="n">t</span>
<span class="c">(* ... *)</span>
<span class="k">end</span>
</pre></div>
</td></tr></table>
<p>D'ailleurs je trouve étrange de pouvoir écrire <code>Exp.ISet [Value.Int 1; Value.Int 2]</code> et de voir que j'ai <code>IntSet.t Exp.t</code> comme type puisque je ne manipule pas vraiment de Set là.</p>
</blockquote>
<p>Le type utilisé pour décorer <code>t</code> dans <code>Exp</code> est juste un «tag». Ça ne veut pas dire que tu as une valeur du type en question. La valeur que tu obtiens est bien du type <code>IntSet.t Exp.t</code> mais le fait que ce soit <code>IntSet.t</code> à cette position dit juste qu'elle a été construite avec le constructeur <code>ISet</code> plutôt que le constructeur <code>FSet</code>. Du coup, je ne pense pas que c'était ce que tu voulais faire.</p>
<p>Tu voulais peut-être faire quelque chose dans ce goût-là ?</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="o">_</span> <span class="k">value</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="kt">int</span> <span class="k">value</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="kt">float</span> <span class="k">value</span>
<span class="k">module</span> <span class="nc">ValueSet</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">module</span> <span class="nc">IntSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span> <span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">int</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="k">module</span> <span class="nc">FloatSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span> <span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">float</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="k">type</span> <span class="o">_</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">FromIntSet</span> <span class="o">:</span> <span class="nn">IntSet</span><span class="p">.</span><span class="n">t</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">FromFloatSet</span> <span class="o">:</span> <span class="nn">FloatSet</span><span class="p">.</span><span class="n">t</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">t</span>
<span class="k">let</span> <span class="n">add</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="k">value</span> <span class="o">-></span> <span class="n">a</span> <span class="n">t</span> <span class="o">-></span> <span class="n">a</span> <span class="n">t</span> <span class="o">=</span> <span class="k">fun</span> <span class="n">v</span> <span class="n">s</span> <span class="o">-></span>
<span class="o">(</span><span class="k">match</span> <span class="n">v</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">v'</span> <span class="o">-></span> <span class="o">(</span><span class="k">match</span> <span class="n">s</span> <span class="k">with</span> <span class="o">|</span> <span class="nc">FromIntSet</span> <span class="n">s'</span> <span class="o">-></span> <span class="nc">FromIntSet</span> <span class="o">(</span><span class="nn">IntSet</span><span class="p">.</span><span class="n">add</span> <span class="n">v'</span> <span class="n">s'</span><span class="o">))</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">v'</span> <span class="o">-></span> <span class="o">(</span><span class="k">match</span> <span class="n">s</span> <span class="k">with</span> <span class="o">|</span> <span class="nc">FromFloatSet</span> <span class="n">s'</span> <span class="o">-></span> <span class="nc">FromFloatSet</span> <span class="o">(</span><span class="nn">FloatSet</span><span class="p">.</span><span class="n">add</span> <span class="n">v'</span> <span class="n">s'</span><span class="o">)))</span>
<span class="k">let</span> <span class="n">mem</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="k">value</span> <span class="o">-></span> <span class="n">a</span> <span class="n">t</span> <span class="o">-></span> <span class="kt">bool</span> <span class="o">=</span> <span class="k">fun</span> <span class="n">v</span> <span class="n">s</span> <span class="o">-></span>
<span class="o">(</span><span class="k">match</span> <span class="n">v</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">v'</span> <span class="o">-></span> <span class="o">(</span><span class="k">match</span> <span class="n">s</span> <span class="k">with</span> <span class="o">|</span> <span class="nc">FromIntSet</span> <span class="n">s'</span> <span class="o">-></span> <span class="nn">IntSet</span><span class="p">.</span><span class="n">mem</span> <span class="n">v'</span> <span class="n">s'</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">v'</span> <span class="o">-></span> <span class="o">(</span><span class="k">match</span> <span class="n">s</span> <span class="k">with</span> <span class="o">|</span> <span class="nc">FromFloatSet</span> <span class="n">s'</span> <span class="o">-></span> <span class="nn">FloatSet</span><span class="p">.</span><span class="n">mem</span> <span class="n">v'</span> <span class="n">s'</span><span class="o">))</span>
<span class="c">(* ... *)</span>
<span class="k">end</span>
<span class="c">(* Exemple : *)</span>
<span class="k">let</span> <span class="n">i</span> <span class="o">=</span> <span class="nc">Int</span> <span class="mi">10</span> <span class="k">in</span>
<span class="nn">ValueSet</span><span class="p">.</span><span class="o">(</span>
<span class="k">let</span> <span class="n">s</span> <span class="o">=</span> <span class="nc">FromIntSet</span> <span class="nn">IntSet</span><span class="p">.</span><span class="n">empty</span> <span class="k">in</span>
<span class="k">let</span> <span class="n">s'</span> <span class="o">=</span> <span class="n">add</span> <span class="n">i</span> <span class="n">s</span> <span class="k">in</span>
<span class="n">mem</span> <span class="n">i</span> <span class="n">s'</span>
<span class="o">)</span>
</pre></div>
</td></tr></table>
<p>Note qu'il y a peut-être moyen de faire ça plus joliment.</p>Evaluation d'expressions & gestion des types, message #460632015-03-01T17:18:14+01:00olzd/@olzdhttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p46063<p>J'ai commencé à jouer avec les GADTs mais j'ai un problème:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">Value</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">type</span> <span class="o">_</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">Bool</span> <span class="o">:</span> <span class="kt">bool</span> <span class="o">-></span> <span class="kt">bool</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="o">:</span> <span class="kt">string</span> <span class="o">-></span> <span class="kt">string</span> <span class="n">t</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="n">t</span> <span class="o">-></span> <span class="n">a</span> <span class="n">t</span> <span class="o">-></span> <span class="kt">int</span> <span class="o">=</span> <span class="k">fun</span> <span class="n">x</span> <span class="n">y</span> <span class="o">-></span>
<span class="k">match</span> <span class="n">x</span><span class="o">,</span> <span class="n">y</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">a</span><span class="o">,</span> <span class="nc">Int</span> <span class="n">b</span> <span class="o">-></span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span> <span class="n">a</span> <span class="n">b</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">a</span><span class="o">,</span> <span class="nc">Float</span> <span class="n">b</span> <span class="o">-></span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span> <span class="n">a</span> <span class="n">b</span>
<span class="o">|</span> <span class="nc">Bool</span> <span class="n">a</span><span class="o">,</span> <span class="nc">Bool</span> <span class="n">b</span> <span class="o">-></span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span> <span class="n">a</span> <span class="n">b</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="n">a</span><span class="o">,</span> <span class="nc">Var</span> <span class="n">b</span> <span class="o">-></span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span> <span class="n">a</span> <span class="n">b</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nc">ValueSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="nc">Value</span><span class="o">)</span>
</pre></div>
</td></tr></table>
<p>J'ai ça comme erreur:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13</pre></div></td><td class="code"><div class="codehilite"><pre>Error: Signature mismatch:
...
Type declarations do not match:
type 'a t =
'a Value.t =
Int : int -> int t
| Float : float -> float t
| Bool : bool -> bool t
| Var : string -> string t
is not included in
type t
File "ast2.ml", line 2, characters 7-127: Actual declaration
They have different arities.
</pre></div>
</td></tr></table>
<p>Bon, je m'y attendais un peu mais du coup je dois faire un truc du genre:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">IntSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">int</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="k">module</span> <span class="nc">FloatSet</span> <span class="o">=</span> <span class="nn">Set</span><span class="p">.</span><span class="nc">Make</span><span class="o">(</span><span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span> <span class="kt">float</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span>
<span class="k">let</span> <span class="n">compare</span> <span class="o">=</span> <span class="nn">Pervasives</span><span class="p">.</span><span class="n">compare</span>
<span class="k">end</span><span class="o">)</span>
<span class="c">(* ... *)</span>
</pre></div>
</td></tr></table>
<p>Mais ça m'oblige à écrire:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">Exp</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">type</span> <span class="o">_</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">ISet</span> <span class="o">:</span> <span class="kt">int</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span> <span class="kt">list</span> <span class="o">-></span> <span class="nn">IntSet</span><span class="p">.</span><span class="n">t</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">FSet</span> <span class="o">:</span> <span class="kt">float</span> <span class="nn">Value</span><span class="p">.</span><span class="n">t</span> <span class="kt">list</span> <span class="o">-></span> <span class="nn">FloatSet</span><span class="p">.</span><span class="n">t</span> <span class="n">t</span>
<span class="c">(* ... *)</span>
<span class="k">end</span>
</pre></div>
</td></tr></table>
<p>D'ailleurs je trouve étrange de pouvoir écrire <code>Exp.ISet [Value.Int 1; Value.Int 2]</code> et de voir que j'ai <code>IntSet.t Exp.t</code> comme type puisque je ne manipule pas vraiment de Set là.</p>Evaluation d'expressions & gestion des types, message #458432015-02-27T17:33:50+01:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p45843<p>J'avais oublié l'existence de l'article <a href="http://mads-hartmann.com/ocaml/2015/01/05/gadt-ocaml.html">Detecting use-cases for GADTs in OCaml</a>, mais c'est une bonne lecture sur le sujet (et d'ailleurs, son exemple d'utilisation correspond presque exactement au tien).</p>Evaluation d'expressions & gestion des types, message #453112015-02-23T23:12:25+01:00olzd/@olzdhttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p45311<p>Woah, merci pour cette réponse détaillée, j'irai voir les GADTs de plus près. Du coup je vais préciser plus en détail ce que je cherche à faire (d'ailleurs j'aurais du commencer par ça).</p>
<p>Mon but est de pouvoir générer des fichiers au format <a href="http://www.satcompetition.org/2009/format-benchmarks2009.html">DIMACS-CNF</a>.</p>
<p>J'ai donc besoin de définir un langage de "haut niveau" qui me permette de générer des clauses. Par exemple:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td><td class="code"><div class="codehilite"><pre>$a = [a ; b ; c] ;; un set contenant les variables a, b et c
$b = [b ; ~d] ;; un set contenant les variables b et non d
$c = card($a) ;; $b = 3
bigand $i, $j in $a, $b do
$i | $j ;; | represente un OU
end
;; le bigand ci-dessus est equivalent a
;; bigand $i in $a do
;; bigand $j in $b do
;; $i | $j
;; end
;; end
</pre></div>
</td></tr></table>
<p>Avec ça, j'ai <mathjax>$$((a \lor b) \land (a \lor \neg d)) \land ((b \lor b) \land (b \lor \neg d)) \land ((c \lor b) \land (c \lor \neg d))$$</mathjax>
Je simplifie/transforme ensuite (si nécessaire) en CNF et je génère mon fichier DIMACS.</p>
<p>En fait, je sais pas vraiment quelle tête devrait avoir mon AST ni comment évaluer tout ça. Je peux toujours faire un truc du genre:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">Ast</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Unit</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="k">of</span> <span class="kt">int</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="k">of</span> <span class="kt">float</span>
<span class="o">|</span> <span class="nc">Term</span> <span class="k">of</span> <span class="kt">string</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="k">of</span> <span class="o">(</span><span class="kt">string</span> <span class="o">*</span> <span class="n">t</span> <span class="n">option</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Set</span> <span class="k">of</span> <span class="n">t</span> <span class="kt">list</span>
<span class="o">|</span> <span class="nc">Card</span> <span class="k">of</span> <span class="n">t</span>
<span class="o">|</span> <span class="nc">Bigand</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Bigor</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">And</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Or</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Xor</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Implies</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Equiv</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Top</span>
<span class="o">|</span> <span class="nc">Bottom</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="k">of</span> <span class="o">(</span><span class="n">t</span> <span class="o">*</span> <span class="n">t</span><span class="o">)</span>
<span class="c">(* ... *)</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nc">Type</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">let</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Unit</span>
<span class="o">|</span> <span class="nc">Int</span>
<span class="o">|</span> <span class="nc">Float</span>
<span class="o">|</span> <span class="nc">Bool</span>
<span class="o">|</span> <span class="nc">Clause</span>
<span class="o">|</span> <span class="nc">Set</span>
<span class="k">end</span>
<span class="k">let</span> <span class="n">toplevel</span> <span class="o">=</span> <span class="nn">Hashtbl</span><span class="p">.</span><span class="n">create</span> <span class="mi">10</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nn">Ast</span><span class="p">.</span><span class="nc">Int</span> <span class="n">x</span> <span class="o">-></span> <span class="nn">Ast</span><span class="p">.</span><span class="nc">Int</span> <span class="n">x</span><span class="o">,</span> <span class="nn">Type</span><span class="p">.</span><span class="nc">Int</span>
<span class="o">|</span> <span class="nn">Ast</span><span class="p">.</span><span class="nc">Float</span> <span class="n">x</span> <span class="o">-></span> <span class="nn">Ast</span><span class="p">.</span><span class="nc">Float</span> <span class="n">x</span><span class="o">,</span> <span class="nn">Type</span><span class="p">.</span><span class="nc">Float</span>
<span class="o">|</span> <span class="nn">Ast</span><span class="p">.</span><span class="nc">Var</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span> <span class="nc">None</span><span class="o">)</span> <span class="o">-></span>
<span class="k">try</span> <span class="nn">Hashtbl</span><span class="p">.</span><span class="n">find</span> <span class="n">toplevel</span> <span class="n">x</span>
<span class="k">with</span> <span class="nc">Not_found</span> <span class="o">-></span> <span class="n">failwith</span> <span class="o">(</span><span class="s2">"unbound variable: "</span> <span class="o">^</span> <span class="n">x</span><span class="o">)</span>
<span class="o">|</span> <span class="nn">Ast</span><span class="p">.</span><span class="nc">Var</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span><span class="nc">Some</span> <span class="n">y</span><span class="o">)</span> <span class="o">-></span>
<span class="k">if</span> <span class="nn">Hashtbl</span><span class="p">.</span><span class="n">mem</span> <span class="n">toplevel</span> <span class="n">x</span> <span class="k">then</span>
<span class="nn">Hashtbl</span><span class="p">.</span><span class="n">replace</span> <span class="n">toplevel</span> <span class="n">x</span> <span class="o">(</span><span class="n">eval</span> <span class="n">y</span><span class="o">)</span>
<span class="k">else</span>
<span class="nn">Hashtbl</span><span class="p">.</span><span class="n">add</span> <span class="n">toplevel</span> <span class="n">x</span> <span class="o">(</span><span class="n">eval</span> <span class="n">y</span><span class="o">)</span> <span class="o">;</span> <span class="nc">Unit</span><span class="o">,</span> <span class="nn">Type</span><span class="p">.</span><span class="nc">Unit</span>
<span class="o">|</span> <span class="nc">Bigand</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span><span class="n">y</span><span class="o">,</span><span class="n">z</span><span class="o">)</span> <span class="k">as</span> <span class="n">b</span> <span class="o">-></span> <span class="n">eval_bigand</span> <span class="bp">[]</span> <span class="n">b</span>
<span class="c">(* ... *)</span>
<span class="ow">and</span> <span class="n">eval_bigand</span> <span class="n">env</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Bigand</span> <span class="o">(</span><span class="n">vars</span><span class="o">,</span> <span class="n">sets</span><span class="o">,</span> <span class="n">body</span><span class="o">)</span> <span class="o">-></span> <span class="c">(* ... *)</span>
</pre></div>
</td></tr></table>
<p>Sachant qu'après évaluation je dois me retrouver avec quelque chose du genre<br>
<code>And (Or (Term "a", Term "b"), Not (Term "c"))</code>.</p>Evaluation d'expressions & gestion des types, message #452902015-02-23T20:57:13+01:00anonyme/@anonymehttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p45290<p>Pour ta première solution, tu ne pourras pas l'utiliser pour écrire une fonction <code>eval</code> qui renvoie directement un <code>int</code> ou un <code>float</code>. Éventuellement, tu peux avoir (j'oublie les variables) :</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">n</span> <span class="o">-></span> <span class="nc">Int</span> <span class="n">n</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">n</span> <span class="o">-></span> <span class="nc">Float</span> <span class="n">n</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">(</span><span class="n">e1</span><span class="o">,</span> <span class="n">e2</span><span class="o">)</span> <span class="o">-></span>
<span class="k">match</span> <span class="n">eval</span> <span class="n">e1</span><span class="o">,</span> <span class="n">eval</span> <span class="n">e2</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">a</span><span class="o">,</span> <span class="nc">Int</span> <span class="n">b</span> <span class="o">-></span> <span class="nc">Int</span> <span class="o">(</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">a</span><span class="o">,</span> <span class="nc">Float</span> <span class="n">b</span> <span class="o">-></span> <span class="nc">Float</span> <span class="o">(</span><span class="n">a</span> <span class="o">+.</span> <span class="n">b</span><span class="o">)</span>
<span class="o">|</span> <span class="o">_</span> <span class="o">-></span> <span class="n">failwith</span> <span class="s2">"eval"</span>
</pre></div>
</td></tr></table>
<p>Cette fonction va « réduire » les noeuds <code>Add</code>, jusqu'à n'avoir plus qu'un noeud <code>Int</code> ou <code>Float</code> dans ton arbre. Si jamais ton arbre est mal construit (il mélange flottants et entiers), tu auras une erreur à l'exécution. Tu ne peux pas vraiment faire mieux. Ensuite, tu peux avoir des fonctions <code>unbox_int</code> et <code>unbox_float</code> qui prennent respectivement en paramètre un <code>Int n</code> et un <code>Float n</code> et te donnent le <code>n</code> correspondant (et échouent sur les autres constructeurs, ce qui leur permet d'être bien typé).</p>
<p>La solution de catamorphisme ne te permettra pas non plus d'avoir <code>eval</code>, pour une raison encore plus simple : les valeurs du type <code>exp</code> ne gardent plus aucune information sur le type (entier ou flottant) de l'expression que tu manipules, tu ne peux donc pas savoir quel opérateur utiliser pour écrire le cas <code>Add</code>. D'ailleurs, rien ne t'empêche de construire une <code>string exp</code> avec le type qu'il propose, ou n'importe quelle autre chose qui n'aurait pas de sens par rapport à la définition que tu as en tête. Par contre, tu peux écrire des fonctions <code>eval_int</code> et <code>eval_float</code>, qui restreignent le type de l'expression d'entrée. L'avantage par rapport à la solution précédente, c'est qu'ici les vérifications ne sont plus dynamiques, mais statiques : tu ne peux plus mélanger des <code>Int</code> et des <code>Float</code> dans une expression (le type te l'interdit), et il est alors possible de type précisément chaque expression bien construite (et de refuser les autres à <em>compile time</em>), donc de vérifier statiquement que les appels à <code>eval_{int,float}</code> se font bien sur des expressions qui ont le bon type. L'inconvénient, c'est que tu retrouves de la duplication de code : tu es obligé de coder plusieurs fonctions <code>eval</code> différentes. Ça peut se simplifier en remarquant qu'elles ont toutes la même structure (c'est un <code>fold</code> sur ton arbre), et qu'on peut donc les coder en utilisant une seule fonction <code>eval_generic : ('a -> 'a -> 'a) -> 'a exp -> 'a</code> qui prend en paramètre un opérateur que tu peux utiliser pour le cas <code>Add</code>. Tu as ensuite <code>let eval_int = eval_generic ( + ) and eval_float = eval_generic ( +. )</code>. Ça devrait normalement fonctionner correctement avec Menhir : si tu n'y arrives pas, tu peux montrer un code minimal pour qu'on voie ce qui ne va pas.</p>
<p>Ta dernière solution revient presque exactement à la première que j'ai développée, sauf qu'au lieu d'utiliser le même type <code>exp</code> pour les expressions « évaluées », tu as un type qui représente ces expressions évaluées. C'est une amélioration de ta première solution.</p>
<p>La solution finale pour faire ce que tu souhaites demande d'utiliser des <a href="http://caml.inria.fr/pub/docs/manual-ocaml-400/manual021.html#toc85">GADT</a>. Le code peut alors ressembler à ça </p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="o">_</span> <span class="n">eval_exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">EInt</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">eval_exp</span>
<span class="o">|</span> <span class="nc">EFloat</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">eval_exp</span>
<span class="k">type</span> <span class="o">_</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="o">:</span> <span class="kt">int</span> <span class="o">-></span> <span class="kt">int</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="o">:</span> <span class="kt">float</span> <span class="o">-></span> <span class="kt">float</span> <span class="n">exp</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">:</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">*</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">-></span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="n">exp</span> <span class="o">-></span> <span class="n">a</span> <span class="n">eval_exp</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">n</span> <span class="o">-></span> <span class="nc">EInt</span> <span class="n">n</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">n</span> <span class="o">-></span> <span class="nc">EFloat</span> <span class="n">n</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-></span>
<span class="k">match</span> <span class="o">(</span><span class="n">eval</span> <span class="n">a</span><span class="o">,</span> <span class="n">eval</span> <span class="n">b</span><span class="o">)</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">EInt</span> <span class="n">x</span><span class="o">,</span> <span class="nc">EInt</span> <span class="n">y</span> <span class="o">-></span> <span class="nc">EInt</span> <span class="o">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">EFloat</span> <span class="n">x</span><span class="o">,</span> <span class="nc">EFloat</span> <span class="n">y</span> <span class="o">-></span> <span class="nc">EFloat</span> <span class="o">(</span><span class="n">x</span> <span class="o">+.</span> <span class="n">y</span><span class="o">)</span>
<span class="k">let</span> <span class="n">full_eval</span> <span class="o">:</span> <span class="k">type</span> <span class="n">a</span><span class="o">.</span> <span class="n">a</span> <span class="n">eval_exp</span> <span class="o">-></span> <span class="n">a</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">EInt</span> <span class="n">n</span> <span class="o">-></span> <span class="n">n</span>
<span class="o">|</span> <span class="nc">EFloat</span> <span class="n">n</span> <span class="o">-></span> <span class="n">n</span>
</pre></div>
</td></tr></table>
<p>Je ne vais pas m'étendre là dessus très longtemps, juste le mentionner pour que tu voies que ça existe et que tu te renseignes dessus si ça t'intéresse. L'idée est d'attacher des informations/contraintes de type aux constructeurs de <code>exp</code>, que le pattern matching peut ensuite utiliser pour s'assurer que le filtrage est bien exhaustif. Ici, tout est vérifié statiquement, et tu n'as qu'une seule fonction <code>eval</code> à écrire (qui est ici découpée en deux, mais ça revient au même). </p>Evaluation d'expressions & gestion des types, message #451162015-02-22T13:36:44+01:00olzd/@olzdhttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p45116<p><strong>@Catamorphisme:</strong> J'y avais pensé, sauf que ça merde lorsque j'écris le parser (avec menhir). J'ai des règles paramétriques et j'arrive pas à faire marcher tout ça <img alt="^^" src="/static/smileys/hihi.png"> .</p>
<p>Sinon je fais un truc du genre:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">module</span> <span class="nc">Type</span> <span class="o">=</span> <span class="k">struct</span>
<span class="k">type</span> <span class="n">t</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="k">of</span> <span class="kt">int</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="k">of</span> <span class="kt">float</span>
<span class="k">end</span>
</pre></div>
</td></tr></table>
<p>Et j'ai ce que je veux, plus ou moins:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="n">env</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="k">of</span> <span class="n">x</span> <span class="o">-></span> <span class="nn">Type</span><span class="p">.</span><span class="nc">Int</span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="k">of</span> <span class="n">f</span> <span class="o">-></span> <span class="nn">Type</span><span class="p">.</span><span class="nc">Float</span> <span class="n">f</span>
<span class="c">(* ... *)</span>
</pre></div>
</td></tr></table>Evaluation d'expressions & gestion des types, message #450902015-02-22T04:43:18+01:00Catamorphisme/@Catamorphismehttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p45090<p>Salut,</p>
<p>je vois deux conceptions possibles. La première est de convertir tous tes Int en Float. La deuxième est de considérer que ce sont deux types indépendants qui ne peuvent pas co-exister (à moins de faire appel <em>explicitement</em> à des fonctions de conversion) et ça revient à ta séparation en expressions entières et flottantes. Sauf que tu peux éviter ta duplication de code en utilisant le polymorphisme paramétrique :</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Scalar</span> <span class="k">of</span> <span class="k">'</span><span class="n">a</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="k">of</span> <span class="kt">string</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="k">of</span> <span class="o">(</span><span class="k">'</span><span class="n">a</span> <span class="n">exp</span> <span class="o">*</span> <span class="k">'</span><span class="n">a</span> <span class="n">exp</span><span class="o">)</span>
</pre></div>
</td></tr></table>
<p>Petit test :</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2</pre></div></td><td class="code"><div class="codehilite"><pre><span class="nc">Add</span> <span class="o">(</span><span class="nc">Scalar</span> <span class="mi">1</span><span class="o">.</span><span class="mi">3</span><span class="o">,</span> <span class="nc">Scalar</span> <span class="mi">3</span><span class="o">.</span><span class="mi">7</span><span class="o">);;</span>
<span class="o">-</span> <span class="o">:</span> <span class="kt">float</span> <span class="n">exp</span> <span class="o">=</span> <span class="nc">Add</span> <span class="o">(</span><span class="nc">Scalar</span> <span class="mi">1</span><span class="o">.</span><span class="mi">3</span><span class="o">,</span> <span class="nc">Scalar</span> <span class="mi">3</span><span class="o">.</span><span class="mi">7</span><span class="o">)</span>
</pre></div>
</td></tr></table>Evaluation d'expressions & gestion des types, message #450892015-02-22T02:27:28+01:00olzd/@olzdhttps://zestedesavoir.com/forums/sujet/2515/evaluation-dexpressions-gestion-des-types/?page=1#p45089<p>Bonjour/soir,</p>
<p>J'ai un type (simplifié ici) représentant des expressions arithmétiques:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="k">of</span> <span class="kt">int</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="k">of</span> <span class="kt">float</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="k">of</span> <span class="kt">string</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="k">of</span> <span class="o">(</span><span class="n">exp</span> <span class="o">*</span> <span class="n">exp</span><span class="o">)</span>
</pre></div>
</td></tr></table>
<p>Si je veux évaluer mes expressions:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="n">env</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">x</span> <span class="o">-></span> <span class="n">x</span> <span class="c">(* boom *)</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="n">v</span> <span class="o">-></span> <span class="c">(* ... *)</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span><span class="n">y</span><span class="o">)</span> <span class="o">-></span> <span class="c">(* re-boom *)</span>
</pre></div>
</td></tr></table>
<p>Le problème c'est que je ne peux pas renvoyer un <code>int</code> ou un <code>float</code>.<br>
J'ai pensé à wrapper le retour de <code>eval</code> mais je suis pas vraiment fan de l'idée:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="n">env</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">x</span> <span class="o">-></span> <span class="o">`</span><span class="nc">Int</span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">x</span> <span class="o">-></span> <span class="o">`</span><span class="nc">Float</span> <span class="n">x</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="n">v</span> <span class="o">-></span> <span class="c">(* ... *)</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="o">(</span><span class="n">x</span><span class="o">,</span><span class="n">y</span><span class="o">)</span> <span class="o">-></span> <span class="c">(* ... *)</span>
</pre></div>
</td></tr></table>
<p>Une autre solution serait de séparer mes expressions entières et flottantes:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="n">op</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">If</span> <span class="k">of</span> <span class="o">(</span><span class="n">bool_exp</span> <span class="o">*</span> <span class="n">exp</span> <span class="o">*</span> <span class="n">exp</span><span class="o">)</span>
<span class="ow">and</span> <span class="n">exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int_exp</span> <span class="k">of</span> <span class="n">int_exp</span>
<span class="o">|</span> <span class="nc">Float_exp</span> <span class="k">of</span> <span class="n">float_exp</span>
<span class="ow">and</span> <span class="n">int_exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="k">of</span> <span class="kt">int</span>
<span class="o">|</span> <span class="nc">Var</span> <span class="k">of</span> <span class="kt">string</span>
<span class="o">|</span> <span class="nc">Add</span> <span class="k">of</span> <span class="o">(</span><span class="n">int_exp</span> <span class="o">*</span> <span class="n">int_exp</span><span class="o">)</span>
<span class="ow">and</span> <span class="n">float_exp</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="k">of</span> <span class="kt">float</span>
<span class="o">|</span> <span class="nc">FVar</span> <span class="k">of</span> <span class="kt">string</span>
<span class="o">|</span> <span class="nc">FAdd</span> <span class="k">of</span> <span class="o">(</span><span class="n">float_exp</span> <span class="o">*</span> <span class="n">float_exp</span><span class="o">)</span>
</pre></div>
</td></tr></table>
<p>Mais là ça devient le bordel au niveau des noms des constructeurs (puis c'est surtout que j'écris presque 2 fois la même chose, notamment pour mes fonctions d'évaluation)…<br>
Voilà, je sais pas trop comment faire puisqu'aucune solution ne me semble vraiment correcte. En fait, j'ai l'impression que je m'y prends mal <img alt="^^" src="/static/smileys/hihi.png"> .</p>