Paradigme 1er Ordre Pureté Évaluation Résumé Approches Fonctionnelles de la Programmation e Introduction E Didier Verna EPITA / LRDE [email protected] lrde/̃didier @didierverna didier.verna google+ in/didierverna Plan Paradigme 1er Ordre Pureté Évaluation Résumé Un paradigme de Programmation La Fonction : un Objet de 1re Classe Programmation Fonctionnelle (Im)Pure Évaluation Stricte / Paresseuse Résumé AFP / Introduction – Didier Verna 2/24 Plan Paradigme 1er Ordre Pureté Évaluation Résumé Un paradigme de Programmation La Fonction : un Objet de 1re Classe Programmation Fonctionnelle (Im)Pure Évaluation Stricte / Paresseuse Résumé AFP / Introduction – Didier Verna 3/24 Paradigme 1er Ordre Pureté Un Paradigme de Programmation Évaluation Résumé « Quoi faire » plutôt que « Comment faire » I Un paradigme ? I I I I Affecte l’expressivité d’un langage Affecte la manière de penser dans un langage Le concept de paradigme est poreux Lequel ? I I I Expressions Définitions (expressions nommées) Évaluations (de définitions ou d’expressions) AFP / Introduction – Didier Verna 4/24 Paradigme 1er Ordre De l’Impératif au Fonctionnel Pureté Évaluation Résumé « La somme des carrés des entiers entre 1 et N » C (impératif) Lisp int ssq (int n) { int i = 1, a = 0; while (i <= n) { a += i*i; i += 1; } return a; } (defun ssq (n) (if (= n 1) 1 (+ (* n n) (ssq (1- n))))) Haskell ssq :: Int -> Int ssq 1 = 1 ssq n = n*n + ssq (n-1) C (récursif) int ssq (int n) { if (n == 1) return 1; else return n*n + ssq (n-1); } AFP / Introduction – Didier Verna I Clarté I Concision 5/24 Paradigme De l’Impératif à l’Envers 1er Ordre Pureté Évaluation Résumé « La racine carrée de la somme des carrés de a et de b » C (impératif) Haskell float hypo (float a, float b) { float a2 = a*a; float b2 = b*b; float s = a2 + b2; hypo :: Float -> Float -> Float hypo a b = sqrt ((a*a) + (b*b)) } return sqrt (s); Lisp (defun hypo (a b) (sqrt (+ (* a a) (* b b)))) C (moins impératif) Pour être tout à fait honnête : float hypo (float a, float b) { return sqrt (a*a + b*b); } Haskell (100% préfixe) AFP / Introduction – Didier Verna hypo :: Float -> Float -> Float hypo a b = sqrt ((+) ((*) a a) ((*) b b)) 6/24 Plan Paradigme 1er Ordre Pureté Évaluation Résumé Un paradigme de Programmation La Fonction : un Objet de 1re Classe Programmation Fonctionnelle (Im)Pure Évaluation Stricte / Paresseuse Résumé AFP / Introduction – Didier Verna 7/24 Paradigme La Fonction : un Objet de 1er Ordre 1re Pureté Classe Évaluation Résumé 1er ordre, ordre supérieur etc. I Christopher Strachey (1916-1975) I I I I I I I I nommage (variables) agrégation (structures) argument de fonction retour de fonction manipulation anonyme construction dynamique … Plus d’expressivité (clarté, concision etc.) AFP / Introduction – Didier Verna 8/24 Paradigme 1er Ordre Pureté Nommage, Affectation, Agrégation Évaluation Résumé Aussi simple que d’écrire i = j Haskell backwards :: [a] -> [a] backwards = reverse Scheme (define backwards reverse) Lisp (setf (symbol-function 'backwards) #'reverse) AFP / Introduction – Didier Verna 9/24 Paradigme Arguments Fonctionnels 1er Ordre Pureté Évaluation Résumé Deux archétypes : mapping et folding I I mapping : traiter individuellement les éléments d’une liste par une fonction Lisp Haskell (mapcar #'sqrt '(1 2 3 4 5)) map sqrt [1..5] folding : combiner les éléments d’une liste par une fonction Lisp Haskell (reduce #'+ '(1 2 3 4 5)) foldr1 (+) [1..5] sum [1..5] AFP / Introduction – Didier Verna 10/24 Fonctions Anonymes Paradigme 1er Ordre Pureté Évaluation Résumé Des littéraux comme les autres I I Possibilité de ne pas nommer les fonctions Lisp Haskell (lambda (x) (* 2 x)) \x -> 2 * x Utilisation littérale (comme tout autre type de donnée) Lisp Haskell ((lambda (x) (* 2 x)) 4) (\x -> 2 * x) 4 AFP / Introduction – Didier Verna 11/24 Paradigme 1er Ordre Pureté Retours Fonctionnels (Anonymes) Évaluation Résumé Aussi simple que return 42; Lisp (defun adder (n) (lambda (x) (+ x n))) Haskell adder :: Int -> (Int -> Int) adder n = \x -> x + n AFP / Introduction – Didier Verna 12/24 Pseudo-1er Paradigme 1er Ordre Ordre en Impératif Pureté Évaluation Résumé On fait ce qu’on peut… I Les structures de contrôle impératives sont des formes fixes de fonctions d’ordre supérieur if (expression) { /* ANONYMOUS PROCEDURE ! */ /* blah blah ... */ } else { /* ANONYMOUS PROCEDURE ! */ /* blah blah ... */ } AFP / Introduction – Didier Verna 13/24 Plan Paradigme 1er Ordre Pureté Évaluation Résumé Un paradigme de Programmation La Fonction : un Objet de 1re Classe Programmation Fonctionnelle (Im)Pure Évaluation Stricte / Paresseuse Résumé AFP / Introduction – Didier Verna 14/24 Paradigme 1er Ordre Pureté Programmation Fonctionnelle Pure Évaluation Résumé La fonction au sens mathématique ( 1 si x = 1, ssq(x) = x 2 + ssq(x − 1) sinon. I ssq :: Int -> Int ssq 1 = 1 ssq n = n*n + ssq (n-1) Fonction I I I Haskell Impératif : (procédure) ensemble de calculs à effets de bords avec éventuellement retour d’une valeur Fonctionnel Pur : calcul d’une valeur de sortie (retour) en fonction de valeurs d’entrée (arguments) Variable I I Impératif : stockage d’information qui varie au cours du temps (mutation) Fonctionnel Pur : (constante) valeur inconnue ou arbitraire AFP / Introduction – Didier Verna 15/24 Intérêts de la Pureté Paradigme 1er Ordre Pureté Évaluation Résumé Pureté =⇒ (plus de) sureté I Parallélisme I I Sémantique locale aux fonctions I I Cf. Erlang Tests locaux / Bugs locaux Preuve de programme AFP / Introduction – Didier Verna 16/24 Preuves Formelles Paradigme 1er Ordre Pureté Évaluation Résumé Induction mathématique « Prouvez-moi (s’il vous plaît) que ∀N, ssq(N) > 0 » Fonctionnel pur Impératif Haskell C ssq :: Int -> Int ssq 1 = 1 ssq n = n*n + ssq (n-1) int ssq (int n) { int i = 1, a = 0; while (i <= n) { a += i*i; i += 1; } return a; } I I C’est vrai au rang 1 Supposons que ce soit vrai au rang N − 1… I AFP / Introduction – Didier Verna Euh… 17/24 Paradigme 1er Ordre Pureté Évaluation Limites du Formalisme Mathématique Résumé Comment exprimer le concept de « racine carrée » ? sqrt(x) = y| ( Lisp y >0 y2 = x Lisp (defun sqrtp (s x) (and (> s 0) (= (* s s) x))) (defun sqrt (x) ???) Haskell Haskell sqrtp :: Float -> Float -> Bool sqrtp s x = s > 0 && s*s == x sqrt :: Float -> Float sqrt x = ??? I Au final, il faut bien expliquer comment faire… I Mais on repousse le problème : déclaratif ou impératif ? AFP / Introduction – Didier Verna 18/24 Plan Paradigme 1er Ordre Pureté Évaluation Résumé Un paradigme de Programmation La Fonction : un Objet de 1re Classe Programmation Fonctionnelle (Im)Pure Évaluation Stricte / Paresseuse Résumé AFP / Introduction – Didier Verna 19/24 Paradigme 1er Ordre Pureté Évaluation Stricte / Paresseuse Évaluation Résumé À quel moment calculer la valeur d’une expression ? I I Stricte : Lisp Les arguments (expressions) sont évalués d’abord Paresseuse (lazy) : Haskell Les expressions ne sont évaluées que quand le besoin s’en fait sentir (idem pour les agrégats) AFP / Introduction – Didier Verna 20/24 Paradigme 1er Ordre Pureté Évaluation Stricte / Paresseuse Évaluation Résumé La paresse : une vertu ? I I Intérêt : plus d’abstraction (ex. manipulation de listes infinies) Lisp Haskell (defun intlist (s) (cons s (intlist (1+ s)))) intlist :: Int -> [ Int ] intlist s = s : intlist (s + 1) ;; KO -- OK Contrainte : pureté fonctionnelle requise (on ne peut pas s’appuyer sur l’ordre d’évaluation) AFP / Introduction – Didier Verna 21/24 Paradigme 1er Ordre Pseudo-Paresse en Impératif Pureté Évaluation Résumé On ne fait toujours que ce qu’on peut… I Les structures de contrôle impératives sont des formes embryonnaires d’évaluation paresseuse. if (1) { /* COMPUTED */ /* blah blah ... */ } else { /* NOT COMPUTED ! */ /* blah blah ... */ } AFP / Introduction – Didier Verna 22/24 Plan Paradigme 1er Ordre Pureté Évaluation Résumé Un paradigme de Programmation La Fonction : un Objet de 1re Classe Programmation Fonctionnelle (Im)Pure Évaluation Stricte / Paresseuse Résumé AFP / Introduction – Didier Verna 23/24 Paradigme 1er Ordre Pureté Évaluation Bénéfices de l’Approche Fonctionnelle Résumé Les 3 caractéristiques des (bons) langages Primitives Procédures / Données Combinaisons Abstractions I Moins de distinction entre procédures et données I Plus de puissance dans la combinaison I Plus de puissance dans l’abstraction AFP / Introduction – Didier Verna 24/24