Top Banner
“Tout ce que vous avez toujours voulu savoir sur la programmation fonctionnelle* *sans jamais oser le demander” François Sarradin Xebia IT Architects
62

Programmation Fonctionnelle

Jun 30, 2015

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Programmation Fonctionnelle

“Tout ce que vous aveztoujours voulu savoir sur la

programmation fonctionnelle**sans jamais oser le demander”

François Sarradin

Xebia ITArchitects

Page 2: Programmation Fonctionnelle

● "Bien pour la programmation concurrente" ● "Moins de bugs" ● To reduce cyclomatic complexity is far more important than to

reduce the number of LOCs. Incidentally FP gives a great help to lower both -- @mariofusco

● "Un autre point de vue sur son langage quotidien" ● "Ça retourne le cerveau, pour le bien !"

Programmation fonctionnelleCe qu'on en dit...

Page 3: Programmation Fonctionnelle

○ "Ellitiste" ○ "Difficile à apprendre" ○ "À ne pas mettre entre toutes les mains" ○ "Purement académique" ○ "Ça retourne le cerveau"

Programmation fonctionnelleCe qu'on en dit aussi...

Page 4: Programmation Fonctionnelle

OK, mais...

Qu'est-ce que laprogrammation fonctionnelle ?

Page 5: Programmation Fonctionnelle

Récursion

Fonction

Monade

Monoïde

Lazy evaluation

Tail recursion

Curryfication

Point freePattern matching

ProgrammationFonctionnelle

Combinateur de point fixe

Continuation

Closuremap/filter/fold/zip

Lambda calcul

Inférence de type

Catamorphisme

Type system

Functor

Ordre supérieur

Type algébrique

Transparence référentielle

Page 6: Programmation Fonctionnelle

Au programme...

● La base du style fonctionnel○ Histoire de la programmation fonctionnelle○ Récursion / Ordre supérieur / Déterminisme○ Optimisation

● Traitement de flux d'informations

○ Liste en programmation fonctionnelle○ Fonctions sur listes

● Conclusion

● Hands On

Page 7: Programmation Fonctionnelle

● Haskell (principalement) ● Scala, Clojure, Erlang, etc.

● Java + Guava (pour le Hands On)

Langages utilisés

Page 8: Programmation Fonctionnelle

Commençons

Page 9: Programmation Fonctionnelle

Soit la fonction factorielle

"n! est le produit des entiers compris entre 1 et n"

ou

n! = 1 * ⋯ * n = Πi i , ∀ i ∈ [1..n]

ou

0! = 1,n! = n . (n - 1)!, si n > 0.

Page 10: Programmation Fonctionnelle

StyleFonctionnel

int fact(int n): result = 1 for i in [1..n]: result = result * i return result

fact n = product [1..n](haskell)

Impératif

(defn fact [n] (reduce * 1 (range 1 (inc n))))

(clojure)

fact(0) -> 1;fact(N) -> N * fact(N - 1).

(erlang)

public int fact(int n) { if (n == 0) return 1; else return n * fact(n-1);}

(java)

Page 11: Programmation Fonctionnelle

Et aussi...

Point freeComposition de fonctions + disparition des variables ContinuationFutur de la fonction en paramètre Combinateur de point fixePermet les fonctions anonymes et récursives MonadeChaînage de traitements

Page 12: Programmation Fonctionnelle

Mais aussi des dérives...

factorial←{⍺←1⍵=0:⍺(⍺×⍵)∇ ⍵-1

}

life←{ ↑1 ⍵∨.^3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵ }

APL (A Programming Language)

Page 13: Programmation Fonctionnelle

Programmation fonctionnellePrincipe n°1 : tout est fonction

Page 14: Programmation Fonctionnelle

Tout est fonctionAu sens mathématique

f(x) = 2.x

x ↦ x + 42

h(x, y) = ∂2 p(x, y) / ∂x2

Page 15: Programmation Fonctionnelle

FonctionDans les langages fonctionnels

Haskellidentity x = x\x -> x

Scaladef identity(x: Any) = x{ x: Any => x }

Clojure(defn identity [x] x)(fn [x] x)

Page 16: Programmation Fonctionnelle

FonctionAvec Guava

new Function<T, R>() { @Override public R apply(T x) { return x; }} new Predicate<T>() { @Override public boolean apply(T x) { return x == null; }}

Page 17: Programmation Fonctionnelle

Programmation fonctionnelleD'où est-ce que ça vient ?

Page 18: Programmation Fonctionnelle

Fonction mathématiquefin du XVIIe siècle

f : x ↦ x f : x ↦ 2 . x

ou

f(x) = 2 . xGottfried Wilhelm von Leibniz(1646-1716)

Page 19: Programmation Fonctionnelle

λx.x(λx.2*x) 7 → 2 * 7 true ::= λxy.xfalse ::= λxy.yif-then-else ::= λpab.p a b 0 ::= λfx.x1 ::= λfx.f x2 ::= λfx.f (f x)

Lambda-calcul1936

Alonzo Church(1903-1995)

Page 20: Programmation Fonctionnelle

(lambda (x) x)(f arg1 arg2 ...)(lambda (x) (* 2 x)) (cons A B)(car (cons A B)) => A(cdr (cons A B)) => B

LISP1958

John McCarthy (1927-2011)

Page 21: Programmation Fonctionnelle

Et ensuite...

Lisp (1958) Scheme (1975) Common Lisp (1984) Clojure (2007)

APL (1964) FP (1977) J (1990)

ISWIM (1966) ML (1973) Caml (1985) F# (2002) Haskell (1987) Scala (2003)

Forth (1970s) PostScript (1982) RPL (1984) Joy (2001)

Prolog (1972) Erlang (1986)

Page 22: Programmation Fonctionnelle

Version "embarqué"

● Langage○ Java 8 (en 2012 ?)○ Groovy○ Python○ Ruby○ SmallTalk○ ...

● API Java

○ Guava○ LambdaJ○ TotallyLazy○ FunctionalJava○ FunkyJFunctional

Page 23: Programmation Fonctionnelle

Success stories

● Banque / finance○ Jane Street (OCaml)○ Goldman Sachs (Erlang), CitiGroup (Clojure), ...

● Réseaux sociaux○ Twitter (Scala)○ FourSquare (Scala/Lift)○ Facebook (Erlang)

● Télécommunication○ Ericsson (Erlang)

● Autres...○ Microsoft (F#)○ CouchDB, RabbitMQ (Erlang)

Page 24: Programmation Fonctionnelle

Programmation fonctionnellePrincipe n°2 : récursion

Page 25: Programmation Fonctionnelle

Récursion

Boucle = fonction qui s'appelle elle même fact n = if n == 0 then 1 else n * fact (n-1)

Proscrire ○for○while○repeat○ etc.

Verboten !

Stateful !

def fact(n):r = 1for i in [1..n]:

r *= ireturn n

Page 26: Programmation Fonctionnelle

Récursion terminale

L'appel récursif est la dernière instructionfact_t n k = if n == 0 then k else fact_t (n-1) (n*k) fact n = fact_t n 1

Page 27: Programmation Fonctionnelle

Récursion : pile d'appels

-> fact(5) -> fact(4) -> fact(3) -> fact(2) -> fact(1) -> fact(0) <- 1 <- 1 * 1 = 1 <- 2 * 1 = 2 <- 3 * 2 = 6 <- 4 * 6 = 24<- 5 * 24 = 120

fact n = if n == 0 then 1 else n * fact (n-1)

Page 28: Programmation Fonctionnelle

Récursion terminale : pile d'appels

-> fact_t 5 1 -> fact_t 4 5 -> fact_t 3 20 -> fact_t 2 60 -> fact_t 1 120 -> fact_t 0 120 <- 120 <- 120 ...<- 120

fact_t n k = if n == 0 then k else fact_t (n-1) (n*k)

Page 29: Programmation Fonctionnelle

Récursion : beware !

Page 30: Programmation Fonctionnelle

Programmation fonctionnellePrincipe n°3 : ordre supérieur

Page 31: Programmation Fonctionnelle

Fonction d'ordre supérieurFonction en paramètre

Dérivéederiv(f, x) = d f(x) / dt

Application d'une fonction sur chaque élément d'une collection (Java 8 ?)

Arrays.asList(1, 2, 3).map(x -> x * x)

Page 32: Programmation Fonctionnelle

Fonction d'ordre supérieurFonction en sortie

Additionneur (curryfier)add : x ↦ (y ↦ x + y)

add_one = add 1

add_one 2 => 3add_one 10 => 11

Page 33: Programmation Fonctionnelle

Fonction d'ordre supérieur... ou les deux

Compositionf ∘ g : x ↦ f(g(x))

Page 34: Programmation Fonctionnelle

● Généricité / Réutilisation du code● Extension du langage / DSL interne

// Scalanew Order to buy(100 sharesOf "IBM") maxUnitPrice 300 using premiumPricing

new Order to sell(200 bondsOf "Sun") maxUnitPrice 300 using { (qty, unit) => qty * unit - 500 }

Ordre supérieurApports

Page 35: Programmation Fonctionnelle

Programmation fonctionnellePrincipe n°4 : déterminisme

Page 36: Programmation Fonctionnelle

● Fonction = Opération déclarative○ Indépendante + sans état interne + déterministe

Une fonction retourne toujours la même valeur pourvu qu'on lui fournisse les mêmes paramètres => Un bon point pour la programmation concurrente !=> (+) de testabilité, (-) d'effet de bord

Indépendance / Déterminisme

f(x) = x + time() => NON !f(x, t) = x + t => OUI !

Page 37: Programmation Fonctionnelle

x = x + 1 => NON !y = x + 1 => OUI !

● Variable (fonctionnelle)

= variable (mathématique)= constante (impératif)= final (Java)

=> Encore un bon point pour la programmation concurrente !=> (-) d'effet de bord

Immuabilité

Page 38: Programmation Fonctionnelle

Programmation fonctionnelleDéterminisme => Optimisation

Page 39: Programmation Fonctionnelle

Optimisation des fonctions récursives terminales

def fact(n, k): if n == 0: return k return fact(n - 1, k * n)

devient

def fact(n, k): while not (n == 0): k = k * n n = n - 1 return k

OptimisationStyle trampoline

Page 40: Programmation Fonctionnelle

Transparence référentielleUne expression peut être remplacée par son résultat sans changer le comportement du programme MémoizationConserver en cache le résultat d'une fonction selon ses paramètres

Optimisation

Page 41: Programmation Fonctionnelle

Flot de contrôle non linéaireSi aucune dépendance ne les lient, 2 fonctions peuvent être appelées dans n'importe quel ordre Évaluation retardéeÈvaluation selon le besoin Garbage collector-- Since 1958 --

Optimisation

Page 42: Programmation Fonctionnelle

Inférence de typeDéterminer automatiquement le type d'une expression ou d'une fonction Pattern matchingAppliquer un traitement sur une valeur selon son "aspect"=> switch-case on steroid!

value match { // Scala case 1 => ... case "hello" => ... case x:Int => ... case Symbol(a, b) => ...}

Sucre syntaxique

Page 43: Programmation Fonctionnelle

Programmation fonctionnellePrincipe n°5 : liste

Page 44: Programmation Fonctionnelle

Liste de vide[]

Ajouter un élément en tête

1 : [] == [1]1 : [2, 3] == [1, 2, 3]1 : 2 : 3 : [] == [1, 2, 3]

Récupérer la tête

head [1, 2, 3] == 1 Récupérer la queue

tail [1, 2, 3] == [2, 3]

ListeOpérations de base (Haskell)

Page 45: Programmation Fonctionnelle

ListeFinie

Haskell[1,2,3,4,5] => [1, 2, 3, 4, 5][1..5] => [1, 2, 3, 4, 5]['a'..'z'] => "abcdefghijklmnopqrstuvwxyz" Scala(1 to 5) => Range(1, 2, 3, 4, 5)('a' to 'z') => NumericRange(a, b,[...], y, z) Clojure(range 1 5) => (1 2 3 4)

Page 46: Programmation Fonctionnelle

ListeVers l'infini et au delà !

Haskell[1..] => [1, 2, 3, 4, 5, ...tail [1..] => [2, 3, 4, 5, 6, ...take 3 [1..] => [1, 2, 3]take 3 (drop 5 [1..]) => [6, 7, 8] ScalaN/A Clojure(range 1) => (1 2 3 4 5 6 ...

Page 47: Programmation Fonctionnelle

Iterator<Integer> oneToFiveIterator = new AbstractIterator<Integer>() { private int i = 1; @Override protected Integer computeNext() { if (i > 5) return endOfData(); else return i++; } };// évaluation retardée selon Java !

Et en Java + GuavaÉmuler les listes : iterator

Page 48: Programmation Fonctionnelle

Iterable<Integer> oneToFive = new Iterable<Integer>() { @Override public Iterator<Integer> iterator() { return oneToFiveIterator; } }; assertThat(oneToFive)

.containsExactly(1, 2, 3, 4, 5);

Et en Java + GuavaÉmuler les listes : iterable

Page 49: Programmation Fonctionnelle

Et en Java + GuavaListe infinie : suite de 1

Iterator<Integer> onesIterator = new AbstractIterator<Integer>() { @Override protected Integer computeNext() { return 1; }} Iterable<Integer> ones = new Iterable<Integer>() { @Override public Iterator<Integer> iterator() { return onesIterator; }}

Page 50: Programmation Fonctionnelle

Programmation fonctionnelleOpérations de traitement sur listes

Page 51: Programmation Fonctionnelle

mapApplique une transformation sur chaque élément d'une liste

=> Guava : transform(iterable, function)

Haskellmap (+1) [1..5] => [2, 3, 4, 5, 6]

filterConserve que les éléments satisfaisant un prédicat

=> Guava : filter(iterable, predicate)

Haskellfilter (> 3) [1..5] => [4, 5]

Fonction sur listemap et filter

Page 52: Programmation Fonctionnelle

Fonction sur listezip

zipFusionne deux listes

zipWith f [a1, ..., an] [b1, ..., bm] => [f(a1, b1), ..., f(an, bn)]si n < m HaskellzipWith (+) [1..5] [6..8] => [7, 9, 11]

=> Pas d'équivalent en Guava

Page 53: Programmation Fonctionnelle

foldAgrège les valeurs d'une liste (somme, produit, liste, ...)

foldl f a0 [b1, ..., bn]=>

a1 <- f(a0, b1)a2 <- f(a1, b2)...an-1<- f(an-2, bn-1)return f(an-1, bn)

=> Pas d'équivalent en Guava

Fonction sur listefold/reduce

Page 54: Programmation Fonctionnelle

Fonction sur listefold/reduce

Haskellfoldl (+) 0 [1..5] => 15 product l = foldl (*) 1 lfact n = product [1..n] = foldl (*) 1 [1..n] reverse l = foldl (flip (:)) [] lreverse [1..5] => [5, 4, 3, 2, 1]

Page 55: Programmation Fonctionnelle

En résuméLa programmation fonctionnelle, c'est...

Page 56: Programmation Fonctionnelle

Particularité

● Tout est fonction○ Fonction sur des valeurs (1er ordre)○ Fonction sur des fonctions (ordre supérieur)○ Indépendance / Déterminisme / Immuabilité

● Optimisations diverses

● Récursion ● Traitement sur liste

Et plus encore...

Page 57: Programmation Fonctionnelle

Avantages

● Généricité / réutilisation / modularité ● Meilleure testabilité / fiabilité

● Adapter à la programmation concurrente

● Concision

Écrire du code avec un langage fonctionnel

= écrire des spécifications formelles

Page 58: Programmation Fonctionnelle

Difficulté

● Une façon de penser différente

● Courbe d'apprentissage○ idiomes, patterns, best practices

● Longtemps enfermée dans la communauté scientifique ● Déclaratif

○ Pas de maîtrise du déroulement (plus qu'avec Java)○ Bonne connaissance du compilateur/VM

● Trop de concision tue la lisibilité

Page 59: Programmation Fonctionnelle

Littérature

● Miran Lipovača, Learn You a Haskell for Great Good! (LYAH). Avril 2011. http://learnyouahaskell.com/

● Bryan O'Sullivan, Don Stewart, and John Goerzen, Real World Haskell

(RWH). Novembre 2008. http://book.realworldhaskell.org/

Page 60: Programmation Fonctionnelle

Congrès et User Groups

● International Conference on Functional Programming (ICFP), http://www.icfpconference.org/

● Commercial Users of Functional Programming (CUFP), http://cufp.org/

● Scala Days● Clojure/conj

● Paris Scala User Group (soirée - 1/mois)● Clojure Paris User Group (coding dojo - 1/semaine)

Page 61: Programmation Fonctionnelle

Sites webs

● Haskell : http://haskell.org/○ API doc : http://haskell.org/ghc/docs/7.0-latest/html/libraries/index.

html○ Web console : http://tryhaskell.org/

● Scala : http://www.scala-lang.org/○ API doc : http://www.scala-lang.org/api/current/index.html#package○ Web console : http://www.simplyscala.com/

● Clojure : http://clojure.org/○ API doc : http://clojure.github.com/clojure/, http://clojuredocs.org/○ Web console : http://try-clojure.org/

Page 62: Programmation Fonctionnelle

Hands On : ici...

https://github.com/fsarradin/xke-fp