|
Postscript, PDF | Didier Rémy | Polytechnique, INRIA |
|
|
||||
· | Les listes sont des structures de données récursives, donc elles se parcourent naturellement par des fonctions récursives? |
· | Inversement, les tableaux qui sont une structure de donnée énumérée se parcourent plus par des boucles for. |
|
· | (find )
Trouver un élément
|
· | (iter )
Itérer une opération (effet de bord) sur chaque élément
|
· | (map )
Éventuellement, transformer une collection en une autre de même structure
(map)
|
· | (fold )
Appliquer une transformation sur les éléments de la collection en collectant
les résultats. Ici la collection des résultats est une fonction passée en
paramètre, donc pas nécessairement dans la même structure.
|
List
, Array
, Set
, Map
,
etc. fournissent toutes ces opérations de bases,
mais chaque fois implémentés manuellement.
|
|
|
|
|
iter
ou map
n'est guère plus
difficile:tree_fold leavenode
Noter le parallèle entre données et calcul |
|
tree_fold
prend autant d'arguments a1
... an
que le type tree
a de constructeurs A1
... An
. ai
est d'aritée égale à celle du constructeur Ai
et l'application tree_fold a1 ... anv
revient à remplacer dans v
chaque constructeur Ak
par la fonction ak
, puis à évaluer
l'expression résultante.
|
tree_fold leavenode
à
Node (Node (Leave 1, Leave 2), Leave3)
node (node (leave 1) (leave 2)) (leave3)
.
|
|
list_fold
est égale
à fold_right
(modulo réarrangement des arguments):
|
fold_left
qui est récursive terminale. Cela revient à appliquer fold_right
sur la
liste retournée. fold_left cons' nilt
produit le même résultat que
list_fold cons nil (reverse t)
où cons' xy
is cons yx
.fold_left
est une particularité des listes et ne
se généralise pas: dès qu'il y a plusieurs directions de récursion, il n'y a
plus de forme récursive terminale évidente.
|
tree_fold
: chaque fonction ak
retourne un entier qui mesure la taille du sous-arbre issu de Ak
correspondant, qui ne doit dépendre que la taille que de Ak
et
de la taille des sous-arbres respectifs.
|
[]
et 1 pour le poid du noeud ::
.
|
|
fold
: chaque function ak
retourne ()
. tree
dans
ak
attendent un valeur de type unit, et sont inutiles. Ils peuvent
être supprimés et l'arité de ak
décroît d'autant.ak
ne sont utiles que pour leurs effets de
bord, donc l'ordre d'évaluation est primordiale. (Le plus couremment utilisé
étant un parcours en profondeur, de gauche à droite).fold
peut ne pas être spécifié,
(c'est le cas en Ocaml) car en général un fold n'est pas (ne doit pas)
être utilisé pour faire des effets de bords.
|
fold
est assez général et le plus fréquemment
utilisé.
|
fold
une fois
pour toute, par filtrage sur la structure du type de l'argument, puis en
obtenir automatique des versions spécialisés pour chaque type?· | Essentiellement de typage. |
· | Ce sont des travaux en cours de recherche... |
· | À la rigueur, on pourrait fournir quelques fonctions polytypiques primitives,
sans permettre à l'utilisateur d'en programmer de nouvelles (i.e. générer automatiquement les fonctions de repliage). |
|
· | ce qui est essentiel, que l'utilisateur devra impérativement fournir |
· | ce qui est secondaire, qui pourrait être déduit automatiquement de la structure des types (même, si le programmeur doit encore l'écrire manuellement). |
· | en types abstraits. |
· | types concrets paramétrés. |
|
· | soit il l'importe de façon abstraite |
· | soit il est paramétrique (polymorphe) par rapport à celle-ci. |
|
type exp = | Var of string | Int of int | Plus of exp * exp let rec eval env = function | Var x -> List.assoc x env | Int n -> n | Plus (e1, e2) -> eval env e1 + eval env e2;; |
|
exp_fold
.
Montrer que eval
peut s'exprimer à l'aide de exp_fold
.
Donner une version de exp_fold
avec arguments étiquetés permettant
d'éviter tout confusion. Comparer avec l'écriture directe.
|
|
· | Le schéma de récursion est pris en compte par exp_fold , ce qui n'est
pas le cas pour le pattern matching.
|
· | En contrepartie, le pattern matching est plus géneral: il peut se faire en profondeur, ne pas considérer tous les cas, etc. |
· | Ajout d'un noeud Times of exp *exp
|
· | Renommage du constructeur Times en Produit
|
· | Ajout d'un noeud Sigma of explist
|
|
|
|
|
sexp_fold
.
Le traitement du constructeur S
dans la fonction exp_fold
est
plus difficile. Il est de type exp sexp ->sexp
, donc la récursion se
passe sous le constructeur de type sexp
.
Donner une version exp_sexp_fold
de type:
var:(string -> 'a) -> s:('b -> 'a) -> int:(int -> 'b) -> plus:('a -> 'a -> 'b) -> exp -> 'a |
sexp_map_fold
de type
int:(int -> 'a) -> plus:('b -> 'b -> 'a) -> f:('c -> 'b) -> 'c sexp -> 'a |
exp_fold
) pour
transformer les arbres du type paramètrique. En particulier, on devra
retrouver les fonctions spécialisées exp_fold
et exp_map
en
passant l'identité pour l'argument de nom f
ou les constructeurs
Int
et Plus
pour les arguments de nom
int
et plus
.
En déduire une écriture plus simple de exp_sexp_fold
.
Écrire la fonction vars
à l'aide de exp_sexp_fold
.
|
subterms
. Par exemple,
|
· | Les autres fonctions sont inchangées |
· | Toutefois, elle doivent être réévaluées, car sexp a changé
|
· | Utilisation d'un foncteur pour partager la partie commune. |
|
|
|
|
|
|
|
|
|
|
|
· | Un évaluateur, en séparant la structure de varriable et la gestion de l'environnement des autres concepts (primitives et leur évaluation). |
· | On peut de façon similaire écrire un algorithme d'unification abstrait par rapport à la structure de terme. |
· | On peut facilement modifier la structure des termes sans avoir à réécrire l'algorithme d'unification. |
· | Les termes abstraits (vus par l'algorithme d'unification) ne voient pas leur implémentation concrète: un symbol (abstrait) peut être représenté par plusieurs noeud (concrets). |
|
· | Le type exp est casé en type 'asexp et la partie récursive
|
· | On peut modifier indépendemment les deux parties de la structures, sans dépendre ni affecter l'autre |
· | On doit assembler les deux structures avant de les utiliser. |
· | Une fois assemblées les structures ne sont plus modifiables motif |
· | Les détails sont séparés du code principale, |
· | Cela rends le code principal plus lisible, plus réutilisable, |
· | Les détails deviennet réguliers et pourraient (à l'avenir) être générés mécaniquement |
vars
ci-dessus?
Donner une implémentation directe de vars
de complexité linéaire
(on ramassera les variables dans une liste qu'on passe de noeud en
noeud.
Montrer que l'on peut écrire une version analogue de vars
à partir de la fontion exp_fold
.
This document was translated from LATEX by HEVEA and HACHA.