• Aucun résultat trouvé

Programmation fonctionnelle:

N/A
N/A
Protected

Academic year: 2022

Partager "Programmation fonctionnelle:"

Copied!
45
0
0

Texte intégral

(1)

c 2006 Marc Feeley IFT2030 page 79

Programmation fonctionnelle:

Historique

(1941) Lambda-calcul: inventé par Alonzo Church pour étudier la calculabilité

(1959) Lisp: 1er langage symbolique pour l’IA

• syntaxe simple+uniforme, préfixe parenthésé

• récursion, listes, “garbage collection”

• interactif, système de développement intégré, interprété et compilé

• typage dynamique, polymorphisme

• portée dynamique

(1975) Scheme: Lisp épuré, portée lexicale

(1987) ML: typage statique, syntaxe infixe

(1990) Haskell: fonctionnel pur

(2)

c 2006 Marc Feeley IFT2030 page 80

Programmation fonctionnelle et les mathématiques (1)

La programmation fonctionnelle est fondée sur des bases mathématiques solides

Tout programme est vu comme une fonction mathématique

• Le domaine de la fonction correspond aux données fournies au programme (“l’entrée”)

• L’image de la fonction correspond aux données produites par le programme (“la sortie”)

Exemple:

• Domaine = un nom et un fichier de dossiers

• Image = le dossier qui correspond à ce nom

(3)

c 2006 Marc Feeley IFT2030 page 81

Programmation fonctionnelle et les mathématiques (2)

Un des principes les plus importants en mathématique c’est celui de l’égalité

On se sert de ce principe pour définir les règles de transformation et de preuve d’un système

Ex.: ajouter une valeur égale des deux côtés d’une équation ne change pas sa véracité:

X = Y ⇒ X + Z = Y + Z X = Y ⇒ X × Z = Y × Z

Cela nous permet de résoudre:

a/2 − 1 = 3 ⇒ a/2 − 1 + 1 = 3 + 1 ⇒ a/2 = 4 ⇒ a/2 × 2 = 4 × 2 ⇒ a = 8

(4)

c 2006 Marc Feeley IFT2030 page 82

Transparence référentielle (1)

Principe selon lequel le résultat du programme ne change pas si on remplace une expression par une expression de valeur égale

Ce principe

• Facilite l’analyse d’un programme (pour démontrer qu’il a une certaine propriété ou qu’il fait le calcul désiré)

• Facilite les transformations de programme (pour le rendre plus lisible, en améliorer les performances ou le compiler)

• Exemple: une règle qui dit “X + X = 2 × X” permet de remplacer f(y)+f(y) par 2*f(y)

(5)

c 2006 Marc Feeley IFT2030 page 83

Transparence référentielle (2)

La programmation impérative viole la transparence

référentielle à cause des effets de bords (affectation, changement de contenu des fichiers, ...)

Par exemple

int n = 1;

int f (int x) { n++; return n*x; }

... f(y)+f(y) ... // pas ´egal `a 2*f(y)

En un mot, la programmation fonctionnelle c’est la programmation sans affectation

(6)

c 2006 Marc Feeley IFT2030 page 84

Conséquences de la

transparence référentielle

La valeur d’une expression dépend seulement de la valeur de ses sous-expressions (p.e. la valeur de

E1 + E2 dépend seulement de la valeur de E1 et de E2, et la valeur de E2 n’est pas influencée par E1, et vice versa)

L’ordre d’exécution a beaucoup moins d’importance qu’en programmation impérative (E1 peut être évaluée avant, après ou pendant l’évaluation de E2)

Le modèle de calcul est proche des mathématiques, ce qui permet d’appliquer les mêmes techniques

formelles de preuves et de raisonnement (p.e. preuve par induction)

(7)

c 2006 Marc Feeley IFT2030 page 85

Évaluation d’expression (1)

Déf: L’évaluation d’une expression c’est le processus qui permet de trouver sa valeur

Les langages fonctionnels définissent ce processus d’évaluation comme l’application itérée de règles de

réduction sur l’expression à évaluer jusqu’à l’obtention d’une forme normale (une expression qui ne peut plus être réduite)

Chaque règle de réduction spécifie l’égalité de deux expressions

(8)

c 2006 Marc Feeley IFT2030 page 86

Évaluation d’expression (2)

Exemple de règles de réduction simplifiées pour Scheme:

1. (+ X Y ) = N si N = X + Y 2. (* X Y ) = N si N = X × Y

Ce qui donne cette évaluation:

(+ (* 2 3) (* 4 5))

= (+ (* 2 3) 20)

= (+ 6 20)

= 26

(9)

c 2006 Marc Feeley IFT2030 page 87

Scheme: Introduction

La boucle “read-eval-print” permet un développement interactif

% gsi

Gambit Version 4.0

> (+ 1 (* 2 3) 4) 11

> (/ (expt 8 33) (expt 2 100)) 1/2

> (load "fact.scm")

"/Users/feeley/fact.scm"

> (fact 30)

265252859812191058636308480000000

> (fact "deux")

*** ERROR IN fact, "fact.scm"@3.9 -- (Arg 1) REAL expected (< "deux" 2)

1> (fact 2) 2

1> (exit)

(10)

c 2006 Marc Feeley IFT2030 page 88

Scheme: Syntaxe

Comme tous les langages fonctionnels Scheme est basé sur les expressions (la catégorie syntaxique principale est l’expression)

Expressions:

Constante: -250 "allo" #f

Variable: prix nb-elem petit? +

Expression parenthésée:

( h

op ´eration

i h

arguments

i )

(11)

c 2006 Marc Feeley IFT2030 page 89

Formes spéciales et appel de fonction

( h

op ´eration

i h

arguments

i )

Si hop ´erationi est un mot clé (comme if et lambda)

alors l’évaluation se fait suivant des règles de réduction spéciales (on parle de “forme spéciale”)

Sinon, il sagit d’un appel de fonction: hop ´erationi est la fonction à appeler et hargumentsi sont les paramètres actuels passés par valeur

On utilise la notation “

E => V

” pour indiquer que l’évaluation de l’expression E donne V

Exemple: (+ (* 2 3) (* 4 5)) => 26

(12)

c 2006 Marc Feeley IFT2030 page 90

Scheme: Formes spéciales de base (1)

(if hexpr1i hexpr2i hexpr3i)

• Ex.: (if (< 1 2) 1 2)

• Sémantique opérationnelle 1. évaluer hexpr1i

2. si le résultat n’est pas #f retourner la valeur de hexpr2i sinon retourner la valeur de hexpr3i

• Sémantique par règles de réduction 1. (if #f Y Z) = Z

2. (if X Y Z) = Y si X est une forme normale différente de #f

Évaluation de l’exemple:

(if (< 1 2) 1 2) = (if #t 1 2) = 1

(13)

c 2006 Marc Feeley IFT2030 page 91

Scheme: Formes spéciales de base (2)

(let (

{

(hident1i hexpr1i)

}

) hexpr0i)

• Ex.: (let ((a 5) (b 2)) (+ a b))

• Sémantique opérationnelle 1. évaluer hexpr1i,. . .

2. créer les variables locales hident1i,. . . dont la valeur initiale est donnée par hexpr1i,. . . et dont la portée est hexpr0i

3. retourner la valeur de hexpr0i

(14)

c 2006 Marc Feeley IFT2030 page 92

Scheme: Formes spéciales de base (3)

(let (

{

(hident1i hexpr1i)

}

) hexpr0i)

• Sémantique par règles de réduction

1. (let ((V1 E1)...) E0) = E0 avec toutes les références à V1 remplacées par E1,. . . (il est

important de respecter les règles de portée lexicale et renommer au besoin les variables qui causent

un conflit de nom)

Le let permet d’attacher des noms à des valeurs à l’intérieur d’un bloc

(15)

c 2006 Marc Feeley IFT2030 page 93

Scheme: Formes spéciales de base (4)

On peut faire l’évaluation en

ordre normal: remplacer Vi par Ei dans E0 puis réduire E0 à sa forme normale

ordre applicatif: réduire Ei à leur forme normale avant de substituer

Exemple 1:

(let ((x 2) (y 3)) (+ x y))

= (+ 2 3)

= 5

Exemple 2:

(let ((x (+ 1 2)) (y (* 3 4))) (if (< x y) x y))

(16)

c 2006 Marc Feeley IFT2030 page 94

Scheme: Formes spéciales de base (5)

Exemple 2, évaluation 1 (ordre applicatif)

(let ((x (+ 1 2)) (y (* 3 4))) (if (< x y) x y))

= (let ((x 3)

(y (* 3 4))) (if (< x y) x y))

= (let ((x 3) (y 12))

(if (< x y) x y))

= (if (< 3 12) 3 12)

= (if #t 3 12)

= 3

(17)

c 2006 Marc Feeley IFT2030 page 95

Scheme: Formes spéciales de base (6)

Exemple 2, évaluation 2 (ordre normal)

(let ((x (+ 1 2)) (y (* 3 4))) (if (< x y) x y))

= (if (< (+ 1 2) (* 3 4)) (+ 1 2) (* 3 4)))

= (if (< 3 (* 3 4)) (+ 1 2) (* 3 4)))

= (if (< 3 12) (+ 1 2) (* 3 4)))

= (if #t (+ 1 2) (* 3 4)))

= (+ 1 2)

= 3

Théorème Church-Rosser: la forme normale obtenue est la même quel que soit l’ordre de réduction

(18)

c 2006 Marc Feeley IFT2030 page 96

Scheme: Formes spéciales de base (7)

Exemple 3 avec évaluation en ordre applicatif

(let ((x 1))

(+ (let ((x (+ x 1)) (y (+ x 2))) (* x y)) x))

= (+ (let ((x (+ 1 1)) (y (+ 1 2))) (* x y)) 1)

= (+ (let ((x 2) (y (+ 1 2))) (* x y)) 1)

= (+ (let ((x 2) (y 3)) (* x y)) 1)

= (+ (* 2 3) 1)

= (+ 6 1)

= 7

Pour obtenir la portée lexicale, dans le corps du let on remplace seulement les variables qui sont libres, c’est-à-dire qui ne sont pas l’objet d’un let dans le corps du let

(19)

c 2006 Marc Feeley IFT2030 page 97

Scheme: Formes spéciales de base (8)

Lors de la réduction d’un let il ne faut pas qu’une des expressions substituées pour les variables contienne des variables libres qui ne seront plus libres après la réduction

Pour éviter ce problème on renomme au besoin les variables qui causent un conflit

(20)

c 2006 Marc Feeley IFT2030 page 98

Scheme: Formes spéciales de base (9)

INCORRECT | CORRECT

|

(let ((x 0)) | (let ((x 0))

(let ((y (+ x 1))) | (let ((y (+ x 1))) (let ((x 99)) | (let ((x 99))

(+ x y)))) | (+ x y))))

|

= (let ((x 0)) | = (let ((x 0))

(let ((x 99)) | (let ((y (+ x 1))) (+ x (+ x 1)))) | (let ((x2 99))

| (+ x2 y))))

= (let ((x 0)) |

(+ 99 (+ 99 1))) | = (let ((x 0))

| (let ((x2 99))

= (+ 99 (+ 99 1)) | (+ x2 (+ x 1))))

|

| = (let ((x 0))

| (+ 99 (+ x 1)))

|

| = (+ 99 (+ 0 1))

(21)

c 2006 Marc Feeley IFT2030 page 99

Scheme: Formes spéciales de base (10)

(lambda (

{

hident1i

}

) hexpr0i)

• Ex.: (lambda (x) (* x x))

• Sémantique opérationnelle

• une nouvelle fonction, sans-nom, est créée et retournée (une “fermeture”)

• les paramètres formels de la fonction sont hident1i,. . . (notez l’absence de type)

• lorsque cette fonction est appelée, il y a création des variables locales hident1i,. . . dont la valeur

initiale est donnée par les paramètres actuels et dont la portée est hexpr0i, ensuite la valeur de

hexpr0i est retournée comme résultat de l’appel

(22)

c 2006 Marc Feeley IFT2030 page 100

Scheme: Formes spéciales de base (11)

(lambda (

{

hident1i

}

) hexpr0i)

• Sémantique par règles de réduction

1. ((lambda (V1...) E0) E1...) = (let ((V1 E1)...) E0)

Exemple:

(let ((f (lambda (x) (* x x)))) (f (f 10)))

(23)

c 2006 Marc Feeley IFT2030 page 101

Scheme: Formes spéciales de base (12)

Évaluation en ordre applicatif

(let ((f (lambda (x) (* x x)))) (f (f 10)))

= ((lambda (x) (* x x)) ((lambda (x) (* x x)) 10))

= (let ((x ((lambda (x) (* x x)) 10))) (* x x))

= (let ((x (let ((x 10)) (* x x)))) (* x x))

= (let ((x (* 10 10))) (* x x))

= (let ((x 100)) (* x x))

= (* 100 100)

= 10000

(24)

c 2006 Marc Feeley IFT2030 page 102

Scheme: Environnements (1)

Déf: l’environnement d’évaluation d’une expression c’est l’ensemble des variables qui sont accessibles et leur valeur

Déf: la liaison d’une variable c’est la valeur qui lui est associée dans l’environnement

Exemple: (let ((x (+ 1 2))) ; liaison de x `a 3 (* x x))

L’environnement contient des variables locales (déclarées par let et lambda) et globales

Les variables globales sont soit prédéfinies (i.e. elles sont liées à une valeur standard) ou sont définies

explicitement avec la forme spéciale define

(25)

c 2006 Marc Feeley IFT2030 page 103

Scheme: Environnements (2)

Les variables prédéfinies (telles que +, *, sqrt) sont liées aux fonctions primitives de Scheme

• valeur de + => fn. d’addition (arité variable)

• valeur de sqrt => fn. racine carrée

• valeur de not => fn. négation Booléene

L’appel de fonction a la syntaxe

( hexpr0i

{

hexpr1i

}

)

Les paramètres actuels et hexpr0i sont évalués avec les règles normales d’évaluation

(26)

c 2006 Marc Feeley IFT2030 page 104

Scheme: Environnements (3)

Exemple 1 avec évaluation:

(+ 1 2)

= (#<procedure +> 1 2)

= 3

Exemple 2 avec évaluation:

(let ((x 1) (y 2)) ((if (< x y) * +) x y))

= ((if (< 1 2) * +) 1 2)

= ((if #t * +) 1 2)

= (* 1 2)

= (#<procedure *> 1 2)

= 2

(27)

c 2006 Marc Feeley IFT2030 page 105

Scheme: Environnements (4)

Exemple 3 avec évaluation:

(+ (let ((+ *)) (+ 1 2)) (+ 3 4))

= (+ (* 1 2) (+ 3 4))

= (+ (#<procedure *> 1 2) (+ 3 4))

= (+ 2

(+ 3 4))

= (+ 2

(#<procedure +> 3 4))

= (+ 2 7)

= (#<procedure +> 2 7)

= 9

(28)

c 2006 Marc Feeley IFT2030 page 106

Scheme: Environnements (5)

(define hidenti hexpri)

• pas une expression (i.e. pas de valeur)

• crée la variable globale hidenti et l’initialise à la valeur de hexpri

Programme Scheme = ensemble de définitions globales et une expression à évaluer dans

l’environnement global (la valeur obtenue est le résultat du programme)

(29)

c 2006 Marc Feeley IFT2030 page 107

Scheme: Environnements (6)

Exemple:

(define x 3) (define fact

(lambda (n) (if (< n 2)

1

(* n (fact (- n 1)))))) (fact x)

Évaluation en ordre applicatif:

(fact x)

= (fact 3)

= ((lambda (n) (if (< n 2)

1

(* n (fact (- n 1))))) 3)

(30)

c 2006 Marc Feeley IFT2030 page 108

Scheme: Environnements (7)

= (let ((n 3)) (if (< n 2)

1

(* n (fact (- n 1)))))

= (if (< 3 2) 1

(* 3 (fact (- 3 1))))

= (* 3 (fact (- 3 1))) ;;; apr`es quelques r´ed.

= (* 3 (fact 2)) ;;; apr`es quelques r´ed.

= (* 3 ((lambda (n) ;;; apr`es quelques r´ed.

(if (< n 2) 1

(* n (fact (- n 1))))) 2))

= (* 3 (* 2 1)) ;;; apr`es quelques r´ed.

= 6 ;;; apr`es quelques r´ed.

(31)

c 2006 Marc Feeley IFT2030 page 109

Scheme: Environnements (8)

On peut représenter l’environnement d’évaluation par une chaîne de blocs lexicaux (un bloc par niveau

d’imbrication de fonction, plus l’environnement global)

(define n 10)

(define m (+ 1 2))

(define carre (lambda (x) (* x x))) (carre (+ n m))

fonction racine carrée n :

m : carre : + : sqrt :

3 10

...

environnement global

fonction d’addition fonction mise au carré

(32)

c 2006 Marc Feeley IFT2030 page 110

Scheme: Environnements (9)

À l’activation de carre, un environnement local sera créé en étendant l’environnement global:

environnement local x : 13

n : m : carre : + : sqrt :

3 10

...

environnement global

fonction d’addition fonction mise au carré

fonction racine carrée

Cet environnement est utilisé pour l’évaluation du corps de carre

(33)

c 2006 Marc Feeley IFT2030 page 111

Scheme: Environnements (10)

En général, l’activation d’une fonction crée un environnement qui étend l’environnement

d’évaluation de la lambda-expression (environnement de définition) avec les paramètres de la

lambda-expression

Une fermeture doit donc mémoriser l’environnement d’évaluation de la lambda-expression en plus de la lambda-expression elle même

Schématiquement:

environnement d’évaluation

fermeture lambda−expression

(34)

c 2006 Marc Feeley IFT2030 page 112

Scheme: Environnements (11)

Donc on a en fait:

(lambda (x) (* x x)) n :

m : carre : + : sqrt :

3 10

...

environnement global

fonction d’addition fonction racine carrée

Et à l’activation de carre:

(lambda (x) (* x x)) 13

environnement local x :

n : m : carre : + : sqrt :

3 environnement global 10

fonction d’addition fonction racine carrée

(35)

c 2006 Marc Feeley IFT2030 page 113

Scheme: Environnements (12)

Exemple avec environnement imbriqué:

(define f

(lambda (x) (lambda (y)

(+ x y))))

(define g (f 11)) (g 22)

environnement d’évaluation f :

g : ...

environnement global

(36)

c 2006 Marc Feeley IFT2030 page 114

Scheme: Environnements (13)

Exemple avec environnement imbriqué:

(define f

(lambda (x) (lambda (y)

(+ x y))))

(define g (f 11)) (g 22)

environnement global

environnement d’évaluation f : (lambda (x) (lambda (y) (+ x y))) g :

...

(37)

c 2006 Marc Feeley IFT2030 page 115

Scheme: Environnements (14)

Exemple avec environnement imbriqué:

(define f

(lambda (x) (lambda (y)

(+ x y))))

(define g (f 11))

(g 22)

environnement global

environnement d’évaluation f : (lambda (x) (lambda (y) (+ x y))) g :

...

(38)

c 2006 Marc Feeley IFT2030 page 116

Scheme: Environnements (15)

Exemple avec environnement imbriqué:

(define f

(lambda (x) (lambda (y)

(+ x y))))

(define g (f 11)) (g 22)

environnement global x : 11

environnement d’évaluation

(lambda (x) (lambda (y) (+ x y))) f :

g : ...

(39)

c 2006 Marc Feeley IFT2030 page 117

Scheme: Environnements (15)

Exemple avec environnement imbriqué:

(define f

(lambda (x) (lambda (y)

(+ x y)))) (define g (f 11)) (g 22)

environnement global x : 11

environnement d’évaluation f : (lambda (x) (lambda (y) (+ x y))) g : (lambda (y) (+ x y))

...

(40)

c 2006 Marc Feeley IFT2030 page 118

Scheme: Environnements (16)

Exemple avec environnement imbriqué:

(define f

(lambda (x) (lambda (y)

(+ x y)))) (define g (f 11)) (g 22)

environnement global x : 11

environnement d’évaluation f : (lambda (x) (lambda (y) (+ x y))) g : (lambda (y) (+ x y))

...

(41)

c 2006 Marc Feeley IFT2030 page 119

Scheme: Environnements (17)

Exemple avec environnement imbriqué:

(define f

(lambda (x) (lambda (y)

(+ x y))))

(define g (f 11)) (g 22)

environnement global environnement d’évaluation y : 22

x : 11

(lambda (x) (lambda (y) (+ x y))) f :

g : (lambda (y) (+ x y)) ...

(42)

c 2006 Marc Feeley IFT2030 page 120

Scheme: Environnements (18)

On obtient le même résultat par réduction:

(g 22)

= ((f 11) 22)

= (((lambda (x) (lambda (y) (+ x y))) 11) 22)

= ((let ((x 11)) (lambda (y) (+ x y))) 22)

= ((lambda (y) (+ 11 y)) 22)

= (let ((y 22) (+ 11 y)))

= (+ 11 22)

= 33

(43)

c 2006 Marc Feeley IFT2030 page 121

Types

Le concept de type n’est pas attaché aux variables

Le type est associé aux données seulement (p.e. entier, réel, caractère, Booléen, etc)

Exemple:

(define sinon

(lambda (x y z)

(if (not x) y z))) (sinon #f #t #f) => #t (sinon #t 11 22) => 22

(let ((a (sinon (< b 0) 1 #f)))

...) ; a sera li´ee `a un entier ou un Bool´een

(44)

c 2006 Marc Feeley IFT2030 page 122

Types: Nombres (1)

Scheme supporte la “tour des nombres” et le concept d’exactitude

1. entier: 3 #b101 -7179872312398 3.0

2. rationnel: 3 1/2 .5 1.3e-10

3. complexe: 3 1/2 .5 +i 1.9-5.3i

Déf: Un nombre est exact s’il n’y a pas de perte de précision dans son calcul

• exact: (sqrt 9) => 3

• inexact: (sqrt 2) => 1.414213562373

(45)

c 2006 Marc Feeley IFT2030 page 123

Types: Nombres (2)

Fonctions primitives

(+ 9 6) => 15 (- 9 6) => 3 (* 9 6) => 54 (/ 9 6) => 3/2

(quotient 9 6) => 1 (modulo 9 6) => 3 (= 9 9.0) => #t (< 4 1) => #f

(max 1 9 5) => 9 (sqrt 1/9) => 1/3 (sqrt -1) => +i

(exp 1) => 2.718281828 (sin 1.5) => .9974949866

(asin 2) => 1.570796326-1.3169578969i

Références

Documents relatifs

Cet exercice bonus rapporte quelques points supplémentaires seulement si le travail est original (c'est à dire non copié sur un camarade).. Envoyer de préférence l'algorithme au

Delassus se fût borné à dire qu'il avait retrouvé mes résultats, ou plutôt certains de mes résultats, avec quelque chose en plus, il eût été dans le vrai, et cette pré- tention

Développer et réduire l'expression E.. 2) Factoriser C (on réduira l'écriture de chaque facteur).. Ecrire D sous la forme d'un produit de deux facteurs. 3) Factoriser F (on

mineurs ayant pour plus grand commun diviseur À 3 ; nows savons calculer des polynômes entiers dont les produits par ces mineurs ont une somme égale a A 3 ; ces polynômes peuvent

L’accès aux archives de la revue « Nouvelles annales de mathématiques » implique l’accord avec les conditions générales d’utilisation ( http://www.numdam.org/conditions )..

consiste en ce que les forces concourantes, normales aux faces tfun polyèdre fermé et proportionnelles aux superficies de ces faces, forment un système en équi- libre. Car

Ce sont des guidages « isostatiques » : Ils mettent en œuvre, entre les deux ensembles (glissière et coulisseau), les zones de contact

3) On choisit libre d’afficher les pyramides réduites de remplissage soit par type de position soit la totalité pour ensuite compter le nombre par type de pyramide et ainsi avoir