Programmation Fonctionnelle Avancée
Plan du cours : structures de données fonctionnelles efficaces
IStructures de données persistantes
IRaisonnement équationnel
IQueues et Dequeues
IArbres Red-Black
IExemples dans la librairie standard : Set et Map
ITableaux fonctionnels de Paulson
IPour en savoir plus
Programmation Fonctionnelle Avancée
Description des objectifs
Réaliser des structures de données fonctionnelles
Iafin de pouvoir prouver des propriétés des programmes
equationnellement
Iet garder facilement la version avant la modification
Ion ne modifie pas en place la structure de donnée.
On veut faire cela de façon efficace
Programmation Fonctionnelle Avancée
Raisonnement équationnel
Prouver des propriétés équationnellement
Si on n’utilise pas de structures de données mutables
(enregistrements, tableaux, etc.), on peut prouver des propriétes de
programmes par simple application du raisonnement équationnel :
Iremplacement d’égaux par égaux
Iinduction bien fondée
Programmation Fonctionnelle Avancée
Raisonnement équationnel
Exemple
l e t rec append l 1 l 2 =
match l 1 with
[ ] > l 2
| a : : r > a : : ( append r l 2 ) ; ;
Prouvons que append est associative.
l1l2l3.append(append l1l2)l3=append l1(append l2l3)
Programmation Fonctionnelle Avancée
Raisonnement équationnel
Preuve par induction structurelle
Par induction structurelle sur l1.
Cas l1=[].
append (append [] l2) l3 = append l2 l3
= append [] (append l2 l3)
Cas l1=a::r.
append (append (a : :r) l2) l3 = append (a : :(append r l2)) l3
= a : :(append (append r l2) l3)
=h.r.a : :(append r (append l2 l3)
= append (a : :r) (append l2 l3)
Programmation Fonctionnelle Avancée
Raisonnement équationnel
Exercice
(r e v e r s e n a i v e )
l e t rec r e v = fu n cti o n
[ ] > [ ]
| a : : r > ( r e v r )@[ a ] ; ;
(r e v e r s e e f f i c a c e )
l e t rec rev_append = f un cti o n
( [ ] , l ) > l
| ( a : : l , l ’ ) > rev_append ( l , ( a : : l ’ ) ) ; ;
l e t rev l = rev_append ( l , [ ] ) ; ;
Prouvez rev’ l=rev l, pour toute liste l.
Programmation Fonctionnelle Avancée
Raisonnement équationnel
Pour en savoir plus
Voir le cours de Sémantique : il donne les bases pour
Il’induction bien fondée
Ile raisonnement équationnel sur les structures de données de
premier ordre
Ile λ-calcul, qui est à la base de tous les langages fonctionnels,
Ietc.
Vous trouverez un traitement en profondeur avec des exemples
détaillés (écrit pour SML) dans le livre
L.C. Paulson.
ML for the working programmer.
Cambridge University Press, 1996.
Programmation Fonctionnelle Avancée
Raisonnement équationnel
Structures des données persistantes
Ce principe de raisonnement est correct pour les structures de
données dites persistantes :
Structure de données persistante
Structure de donnée que, lors d’une modification, préserve les
versions précedentes.
Les structures purement fonctionnelles sont immuables : on ne peut
les modifier, mais seulement les copier :
elles sont donc automatiquement persistantes.
Voyons dans la suite quelques exemples significatifs de ces
structures de données.
Programmation Fonctionnelle Avancée
Structures persistantes
Listes
Les listes chainées I
(une l i s t e d e n t i e r s )
l e t l = [1;3;5;7];;
(une f o n c t i o n d i n s e r t i o n dans l o r d r e )
l e t rec i n s e r t x =
fu n cti o n [ ] > [ x ]
| a : : r >i f x > a then a : : ( i n s e r t x r )
e l s e x : : a : : r ; ;
Programmation Fonctionnelle Avancée
Structures persistantes
Listes
Les listes chainées II
(insertion )
l e t l = i n s e r t 4 l ; ;
|| v a l l : i n t l i s t = [ 1 ; 3 ; 4 ; 5 ; 7 ]
(l r e s t e i n t a c t e )
l ; ;
|| : i n t l i s t = [ 1 ; 3 ; 5 ; 7 ]
Programmation Fonctionnelle Avancée
Structures persistantes
Listes
Ce qui se passe en mémoire
On simule la modification en place par
Iune copie de la structure jusqu’á la modification
Il’introduction d’un noeud contenant la modification
Ile partage du reste de la structure
l0//1//3//4
l//1//3//5//7
Le prix à payer pour la persistance :
Iune occupation en mémoire accrue,
Il’introduction d’un ramasse-miettes (garbage collector) pour
recuperer la mémoire non utilisée.
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files fonctionnelles efficaces
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Les files : spécification
Interface
module type FIFO = sig
type ’ a t
exception Empty
v a l empty : ’ a t
v a l is_empty : a t > bool
v a l add : ’ a > ’ a t > ’ a t
v a l remove : ’ a t > ( ’ a ’ a t )
(∗ ∗ l e v e l e x c e p t i o n [ Empty ] s u r une f i l e v i d e )
end ; ;
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files fonctionnelles naîves
Implémentation
module F i f o N a i v e : FIFO = struct
type a t = a l i s t
exception Empty
l e t empty = [ ]
l e t is_empty f = f = [ ]
l e t add a f = f@ [ a ]
l e t remove = fun ct ion
| [ ] > r a i s e Empty
| a : : l > ( a , l )
end ; ;
Inefficace
La concatenation de deux listes (@) est linéaire dans la taille de la
première : l’insertion de néléments peut avoir un coût quadratique !
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files impératives
Interface
module type FIFOIMP = sig
type ’ a t
exception Empty
v a l create : unit > ’ a t
v a l is_empty : a t > bool
v a l add : ’ a > ’ a t > unit
v a l remove : ’ a t > ’ a
(∗ ∗ r a i s e s [ Empty ] i f the queue i s empty )
end ; ;
Attention : on est obligés d’utiliser create pour obtenir une file
vide différente à chaque appel !
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files impératives I
Implementation
module F i f o I m p = struct
exception Empty
type a c e l l =
Vide
| Cons of ’ a a c e l l ref
type ’ a t = { mutable f i r s t : ’ a c e l l ;
mutable l a s t : ’ a c e l l }
l e t c r e a t e ( ) = { f i r s t = V ide ; l a s t = Vide }
l e t is_empty f = f . f i r s t = Vi d e
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files impératives II
l e t add a f = match f . l a s t with
| Vide >(f . f i r s t d o i t e t r e Vide a u s s i )
f . f i r s t <Cons ( a , ref V i de ) ;
f . l a s t <f . f i r s t ;
| Cons (_, r ) > r := Cons ( a , ref Vi d e ) ;
f . l a s t <! r
l e t remove f = match f . f i r s t with
| Vide > r a i s e Empty
| Cons ( a , r ) >
i f f . l a s t = f . f i r s t then f . l a s t <! r ;
f . f i r s t <! r ; a
end ; ;
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files imperatives
Temps d’insertion et extraction constant, mais ce n’est pas une
structure de donnée persistante !
open FifoImp ;;
let f = c r e a t e ( ) ; ;
add 3 f ; ;
|| : u n i t = ( )
f ; ;
|| : i n t F ifoI m p . t =
|| { f i r s t = Cons ( 3 , { c o n t e n t s = V id e } ) ; l a s t = Cons ( 3 , { c o n t e n t s = V id e })
|| }
add 4 f ; ;
|| : u n i t = ( )
f ; ;
|| : i n t F ifoI m p . t =
|| { f i r s t = Cons ( 3 , { c o n t e n t s = Cons ( 4 , { c o n t e n t s = V id e } ) } ) ;
|| l a s t = Cons ( 4 , { c o n t e n t s = V id e }) }
remove f ; ;
|| : i n t = 3
f ; ;
|| : i n t F ifoI m p . t =
|| { f i r s t = C ons ( 4 , { c o n t e n t s = V id e } ) ; l a s t = Cons ( 4 , { c o n t e n t s = V id e })
|| }
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files fonctionnelles efficaces I
Implémentation
module FifoDL : FIFO = struct
exception Empty
type a t = a l i s t a l i s t
l e t empty = ( [ ] , [ ] )
l e t is_empty =
fu n cti o n
([] ,[]) >true
| _ >f a l s e
Programmation Fonctionnelle Avancée
Structures persistantes
Files
Files fonctionnelles efficaces II
l e t add x ( l1 , l 2 ) = ( x : : l1 , l 2 )
l e t remove ( l1 , l 2 ) = match l 2 with
| a : : l > ( a , ( l 1 , l ) )
| [ ] >match L i s t . r e v l 1 with
| [ ] > r a i s e Empty
| a : : l > ( a , ( [ ] , l ) )
end ; ;
Est-ce efficace ? remove appelle List.rev !
1 / 12 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 !