Programmation Fonctionnelle Avancée
Plan du cours: Zippers
ILe problème: naviguer efficacement une structure de données
ICe qui ne marche pas
ICe qui marche: les Zippers de Huet
IExemples
IComment dériver des Zippers pour tout type de données
IPour en savoir plus
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Description des objectifs
Naviguer dans une structure de données (en avant, et en arrière):
Ien gardant la possibilité d’ajouter des valeurs au milieu
Isans faire de copies
Isans pointeurs arrières
Iet de façon efficace
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Premier essai
Des fonctions sur les listes avec position I
(une l i s t e a ve c une p o s i t i o n e t une l o n g u e u r )
type a l i s t p o s = i n t int a l i s t ; ;
(c ha n ge r de p o s i t i o n , temps c o n s t a n t )
l e t agauche = f un c ti o n
( 0 ,_,_) > f a i l w i t h " de b u t ␣de l i s t e "
| ( p , t , l ) > ( p1, t , l ) ; ;
l e t a d r o i t e = f u nc t io n
( p , t , l ) when p=t > f a i l w i t h " f i n de l i s t e "
| ( p , t , l ) > ( p +1, t , l ) ; ;
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Premier essai
Des fonctions sur les listes avec position II
(i n s e r t i o n : temps l i n e a i r e )
l e t i n s e r t _ a t _ p o i n t x ( p , t , l ) =
l e t rec i n s =
fu n ct i on
( 0 , l ) > x : : l
| ( n , y : : r ) > y : : ( i n s ( n1 , r ) )
| _ >a s s e r t f a l s e
i n ( p , t +1 , i n s ( p1, l ) ) ; ;
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Premier essai
Des fonctions sur les listes avec position III
(s u p p r e s s i o n : temps l i n e a i r e )
l e t d e l e t e _ a t _ p o i n t ( p , t , l ) =
l e t rec d e l =
fu n ct i on
( 0 , x : : l ) > l
| ( n , y : : r ) > y : : ( d e l ( n 1, r ) )
| _ >a s s e r t f a l s e
i n ( p , t 1, d e l ( p 1, l ) )
; ;
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Deuxième essai, non fonctionnel
Listes doublement chaînées I
On peut essayer avec des références
t y p e ’ a d l l i s t = N i l | C e l l o f ’ a c e l l
and a c e l l = { i n f o : a ; n e x t : a d l l i s t ref ; p r e v : ’ a d l l i s t ref}
(d e p l a c e m e n t , l i n e a i r e )
let agauche =
function Nil >a s s e r t f a l s e
| C e l l { p r e v=c } when ! c = N i l > f a i l w i t h " D ej a a g auc he "
| C e l l { p r e v=c } > ! c ; ;
(i n s e r t i o n , l i n e a i r e )
let i n s e r t a =
function Nil > C e l l { i n f o=a ; p r e v=ref N i l ; n e x t= ref N i l }
| C e l l c a s d l l >
let c = C e l l { i n f o=a ; p r e v=ref ! ( c . p r e v ) ; n e x t= ref d l l } i n
c . p r e v := c ; c
; ;
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Deuxième essai, non fonctionnel
Listes doublement chaînées II
Ce n’est pas idéal
Ifonctions d’impression du toplevel inutiles (les pointeurs arriere
font des cycles)
Iprogrammation penible et avec des effets de bord (la structure
de donnees n’est plus persistante)
Iil nous faut une idée!
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
Zipper de listes I
Gérard Huet 1997
(un b l o c s u r l a p i l e c o n t i e n t j u s t e un a )
type a p i l e = a l i s t
type a l i s t z i p p e r = a p i l e a l i s t
l e t a_gauche ( p i l e , l i s t e ) = match p i l e with
| [ ] > f a i l w i t h " Deja a gauche "
| a : : l > ( l , a : : l i s t e )
l e t a _ d r o i t e ( p i l e , l i s t e ) = match liste with
| [ ] > f a i l w i t h " Deja ␣a d r o i t e "
| a : : l > ( a : : p i l e , l )
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
Zipper de listes II
l e t i n s e r t v ( p i l e , l i s t e ) = ( p i l e , v : : l i s t e )
l e t d e l e t e ( p i l e , l i s t e ) = match liste with
| [ ] > f a i l w i t h " Trop a d r o i t e ␣ pour e f f a c e r "
| a : : r > ( p i l e , r )
; ;
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
L’intuition derrière les zippers
Considérons une visite récursive d’une liste
l e t rec v i s i t = f un c t i o n
|[] > ( )
| a : : r > v i s i t r
; ;
|| v a l v i s i t : a l i s t > u n i t = <fun>
Lors de la visite de [1;2;3;4], la valeur conservée sur la pile
d’appel, et la valeur du parametre évoluent comme suit:
[] [1;2;3;4]
[1] [2;3;4]
[2;1] [3;4]
[3;2;1] [4]
[4;3;2;1] []
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
L’intuition derrière les zippers, bis
En général
Un zipper représente explicitement l’état de la pile d’appel, et la
valeur courante, lors d’une visite récursive d’une structure de
données.
Ila pile d’appel est une suite de blocs d’activation
Ichaque bloc contient les éléments de la structure de données
qui ne sont pas passés à l’appel récursif, plus un marqueur
indiquant sur quel sous-structure on continue la visite
Dans le cas des listes, on n’a pas utilisé de marqueur, parce-que il y
a une seule soustructure pour continuer la visite.
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
Zipper des arbres binaires I
type ’ a a r b r e = F e u i l l e
| Noeud o f ’ a a arbre a arbre
type marqueur = Gauche | D r o i t e
type a b l o c k = marqueur ’ a a arbre
type a p i l e = a b l o c k l i s t
type ’ a a r b r e z i p p e r = ’ a p i l e ’a arbre
l e t bas_a_gauche ( p i l e , a r b r e ) = match arbre with
| F e u i l l e > f a i l w i t h " F e u i l l e "
| Noeud ( x , t1 , t 2 ) > ( Gauche , x , t 2 ) : : p i l e , t 1
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
Zipper des arbres binaires II
l e t bas_a_droite ( p i l e , a r b r e ) = match arbre with
| F e u i l l e > f a i l w i t h " F e u i l l e "
| Noeud ( x , t1 , t 2 ) > ( D ro i te , x , t 1 ) : : p i l e , t 2
l e t en_haut ( p i l e , a r b r e ) = match p i l e with
| ( Gauche , x , t ) : : p > p , Noeud ( x , a r b r e , t )
| ( D r oi t e , x , t ) : : p > p , Noeud ( x , t , a r b r e )
| _ > f a i l w i t h " Rac in e "
; ;
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
Zipper des arbres n-aires I
type a n a r b r e =
| F e u i l l e of ’ a
| Noeud o f a n a r b r e l i s t
type a b l o c k = a n a r br e l i s t z i p p e r
type a p i l e = a b l o c k l i s t
type ’ a n a r b r e z i p p e r = a p i l e a n a r b r e
l e t a_gauche ( p i l e , a r b r e ) = match p i l e with
| ( a : : lp , l ) : : p > ( l p , a r b r e : : l ) : : p , a
| ( [ ] ,_ ) : : p > f a i l w i t h " Deja a gauche "
| _ > f a i l w i t h " Rac in e "
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
Zipper des arbres n-aires II
l e t a _ d r o i t e ( p i l e , a r b r e ) = match p i l e with
| ( l p , a : : l ) : : p > ( a r b r e : : l p , l ) : : p , a
| (_ , [ ] ) : : p i l e > f a i l w i t h " Deja ␣a d r o i t e "
| _ > f a i l w i t h " Rac in e "
l e t en_bas ( p i l e , a r b r e ) = match arbre with
| Noeud ( a : : a r b r e s ) > ( [ ] , a r b r e s ) : : p i l e , a
| Noeud _ | F e u i l l e _ > f a i l w i t h " Deja en ba s "
l e t en_haut ( p i l e , a r b r e ) = match p i l e with
| ( l p , l ) : : p > p , Noeud ( L i s t . r e v ( l p )@( a r b r e : : l ) )
| _ > f a i l w i t h " Deja en haut "
; ;
Programmation Fonctionnelle Avancée
Manipulation efficace d’une structure de donnée arborescente
Zippers
Utilisations
IHuet était motivé par un éditeur structuré de preuves
ILibrairie Clojure http://clojure.org/other_libraries
ILe gestionnaire de fenêtres XMonad (Haskell)
In this picture we have a window manager managing 6 virtual workspaces. Workspace 4 is currently on
screen. Workspaces 1, 2, 4 and 6 are non-empty, and have some windows. The window currently
receiving keyboard focus is window 2 on the workspace 4. The focused windows on the other non-empty
workspaces are being tracked though, so when we view another workspace, we will know which window
to set focus on. Workspaces 3 and 5 are empty.
Programmation Fonctionnelle Avancée
Construction formelle des zippers
Peut-on construire automatiquement des zippers pour un
type quelconque?
Dériver automatiquement des zippers pour un type quelconque
serait un vrai plus pour un programmeur...
En 2001, Conor McBride observe un phénomène intéressant qui
permet de faire ça en analogie avec la dérivation de fonctions.
Les étapes fondamentales sont les suivantes:
Ion traduit (une sousclasse) des types d’OCaml dans le langage
plus simple des types récursifs
Ion définit formellement la dérivée d’un type récursif
Ion obtient la définition du type du bloc de pile à partir de
cette dérivée
Programmation Fonctionnelle Avancée
Construction formelle des zippers
Les types recursifs polynomiaux
On appelle types récursifs polynomiaux les types produits par la
grammaire suivante, ou xest une variable prise dans un ensemble
denombrable
F::= x|0|1|F+F|F×F|µx.F
Une definition de type en OCaml (ou Haskell, ou SML/NJ, ...) sans
types fonctionnels peut se traduire naturellement dans ces types.
type ’a list = Nil | Cons of ’a * ’a list
devient, en oubliant les noms des constructeurs, et en rendant
explicite la définition récursive
µx.1+’a ×x
Programmation Fonctionnelle Avancée
Construction formelle des zippers
Quelques autres exemples
type ’a tree = Empty | Node of ’a * ’a tree * ’a tree
devient, en oubliant les noms des constructeurs, et en rendant
explicite la définition récursive
µx.1+’a ×x×x
type ’a ntree = Feuille of ’a | Node of ’a ntree list
devient, en oubliant les noms des constructeurs, et en rendant
explicite la définition récursive
µx.’a +x list
c’est à dire
µx.’a + (µy.1+x×y)
Programmation Fonctionnelle Avancée
Construction formelle des zippers
Rappel sur les dérivées des fonctions
On se rappelle, du cours d’Analyse, les formules suivantes:
xx=1
xy=0(x6=y)
xa=0(a constante :1,0,’a etc.)
x(A+B) = xA+xB
x(A×B) = xA×B+A×xB
On les applique, sans états d’âme, à nos définitions de type.
1 / 6 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !