Top Banner
OCaml : un Langage Fonctionnel Alan Schmitt 11 septembre 2018 1 / 104
126

OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Jul 17, 2020

Download

Documents

dariahiddleston
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: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

OCaml : un Langage Fonctionnel

Alan Schmitt

11 septembre 2018

1 / 104

Page 2: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Informations Pratiques

▶ Équipe pédagogique▶ Alan Schmitt (cours, 1 groupe de TP)▶ Barbara Kordy (1 groupe de TP)▶ Chen Qian (1 groupe de TP)▶ Leo Henry (1 groupe de TP)

▶ 4 cours▶ 8 TP + 1 TP noté▶ pas d’examen

https://people.rennes.inria.fr/Alan.Schmitt/teaching/[email protected]

Ne pas utiliser mon adresse à l’INSA

2 / 104

Page 3: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Pourquoi apprendre OCaml ?

Page 4: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Objectifs de ce cours

▶ Comprendre des concepts fondamentaux de la programmation(fonctions, types, récursion)

▶ Apprendre à exploiter les atouts de la programmationfonctionnelle

Pourquoi ?▶ Pourquoi s’intéresser à ce style de programmation ?▶ Peut-on résoudre les mêmes problèmes qu’en C ou Java ?

4 / 104

Page 5: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Pourquoi s’intéresser à la programmation fonctionnelle (1)

Approche favorisant des programmes▶ corrects;▶ lisibles;▶ réutilisables ou modifiables.

Un langage de programmation est un outil pointu. Les langagesfonctionnels sont le résultat de nombreuses années de recherche.

5 / 104

Page 6: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Pourquoi s’intéresser à la programmation fonctionnelle (2)

Les langages fonctionnels sont proches des mathématiques. Cesont des langages de haut niveau :

▶ permettant de s’abstraire de l’architecture des machine;▶ donnant des programmes clairs et concis;▶ favorisant un développement rapide;▶ fournissant des outils pour une meilleure sûreté (types).

6 / 104

Page 7: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exemple: gestion de la mémoire

Allouer une liste en C:struct list * x1 = malloc(sizeof(struct list));struct list * x2 = malloc(sizeof(struct list));if (x1 == NULL || x2 == NULL) return NULL;x1->hd = 1; x1->tl = x2; x2->hd = 2; x2->tl = NULL;return x1;

Allouer une liste en OCaml1 :: 2 :: []

7 / 104

Page 8: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Pourquoi s’intéresser à la programmation fonctionnelle (3)

De nombreux langages intègrent des aspects fonctionnels:▶ Java▶ Objective C▶ JavaScript▶ Swift

8 / 104

Page 9: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Peut-on tout programmer en OCaml?

9 / 104

Page 10: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

On peut tout programmer en OCaml

La plupart des langages sont Turing complets.Les langages sont des outils. Un bon outil est un outil adapté auproblème.Ce qui peut être important :

▶ la rapidité pour avoir un programme correct,▶ la facilité de maintenance du programme,▶ la performance (en temps ou mémoire) du programme.

10 / 104

Page 11: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Influence

Haskell Scala

F# Swift

TypeScript, …

11 / 104

Page 12: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Influence

https://facebook.github.io/reason/

12 / 104

Page 13: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Grands succès

https://ocaml.org/learn/success.html

13 / 104

Page 14: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Mirage OShttps://mirage.io/

MirageOS is a library operating system that constructsunikernels for secure, high-performance networkapplications across a variety of cloud computing andmobile platforms. Code can be developed on a normalOS such as Linux or MacOS X, and then compiled into afully-standalone, specialised unikernel that runs under aXen or KVM hypervisor.This lets your services run more efficiently, securely andwith finer control than with a full conventional softwarestack.MirageOS uses the OCaml language, with libraries thatprovide networking, storage and concurrency support thatwork under Unix during development, but becomeoperating system drivers when being compiled forproduction deployment.

14 / 104

Page 15: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Apprendre OCaml

http://ocaml.org

15 / 104

Page 16: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Apprendre OCaml : des livres

http://caml.inria.fr/pub/distrib/books/llc.pdf

http://www.pps.jussieu.fr/Livres/ora/DA-OCAML/

http://programmer-avec-ocaml.lri.fr/

16 / 104

Page 17: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Apprendre OCaml : un MOOChttps://tinyurl.com/ocamooc3

Début du cours le 17 septembre

17 / 104

Page 18: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Introduction

Page 19: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Un langage de la famille ML

fonctionnel les fonctions sont des valeurs de première classetypé inférence de types et types polymorphes

let composition f g = fun x -> f (g x)

val composition : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b =<fun>

filtrage avec déclaration de nouveaux typestype cell = T | F

let rule110 triple = match triple with| (T,T,T) | (T,F,F) | (F,F,F) -> F| _ -> T

type cell = T | Fval rule110 : cell * cell * cell -> cell = <fun>

19 / 104

Page 20: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Un langage fonctionnel

▶ en maths:N → Nn 7→ 2n + 3

▶ en C (nom obligatoire, instruction return):int f (int x) { return 2*x + 3; }

▶ en OCamlfun x -> 2*x + 3

Avantages :▶ tout est expression, assemblées comme des briques Lego▶ raisonnement local (pas d’effet de bord)

20 / 104

Page 21: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exemple

let rec fact = fun n -> if n < 2 then 1 else n * (fact (n-1))

let res = fact 10

val fact : int -> int = <fun>val res : int = 3628800

21 / 104

Page 22: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Programmes

Un programme est une suite de phraseslet identifiant = expression

comme danslet rec fact = fun n -> if n < 2 then 1 else n * (fact (n-1))

let res = fact 10

Exécuter un programme, c’est exécuter toutes ses phrases dansl’ordre (pas de main)Exécuter une phrase, c’est calculer la valeur de expression, etd’associer le nom identifiant à cette valeur

22 / 104

Page 23: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Deux outils pour d’exécuter les programmes

InterprèteMéthode interactive pour écrire des programmes. OCaml exécutechaque phrase, et imprime le résultat de son évaluation sous laforme val identifiant : type = valeur.let rec fact = fun n -> if n < 2 then 1 else n * (fact (n-1))

let res = fact 10

val fact : int -> int = <fun>val res : int = 3628800

avantages interactif, permet d’évaluer des programmes partiels,donne les types et valeurs des phrases

inconvénients lent, utilisable que pour le développement duprogramme, OCaml doit être installé

23 / 104

Page 24: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Deux outils pour d’exécuter les programmes

CompilateurUn outil transformant le programme en du code machineocamlopt -o fact fact.ml./fact

avantages rapide, pas besoin d’avoir à installer OCamlinconvénients n’imprime rien, sauf si instruction spécifique

let rec fact = fun n -> if n < 2 then 1 else n * (fact (n-1))

let res = fact 10

let pr = Printf.printf "résultat : %d\n" res

ocamlopt -o fact2 fact2.ml && ./fact2

résultat : 3628800

24 / 104

Page 25: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les définitions

En Caml une définition consiste à donner un nom à une valeurSyntaxelet identifiant = expression

Exemplelet x = 3 + 5

val x : int = 8

Définitions récursivesSi expression mentionne nom (fonctions récursives), on utiliselet rec nom = expression

25 / 104

Page 26: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les définitions

Attention: un nom x désigne la valeur, pas l’expression

let x = 5-3 val x : int = 2

let y = 2*x val y : int = 4

let x = 1 val x : int = 1

let res = y val res : int = 4

26 / 104

Page 27: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Portée des noms

(* À ce niveau aucun nom n’est défini *)

let x =(* x n’est toujours pas défini *)1 + 2

(* x est maintenant défini et vaut 3 *)

let x =(* x vaut toujours 3 *)x + 1 (* le x est l’ancien qui vaut 3 *)

(* un nouveau nom x cache l’ancien, et vaut 4 *)

let rec fact =(* fact est défini, et vaudra le résultat de l’évaluation du reste *)fun n -> if n < 2 then 1 else n * (fact (n - 1))(* le fact ci-dessus est le même que celui qu’on défini *)

27 / 104

Page 28: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Portée des noms

(* À ce niveau aucun nom n’est défini *)

let x =(* x n’est toujours pas défini *)1 + 2

(* x est maintenant défini et vaut 3 *)

let x =(* x vaut toujours 3 *)x + 1 (* le x est l’ancien qui vaut 3 *)

(* un nouveau nom x cache l’ancien, et vaut 4 *)

let rec fact =(* fact est défini, et vaudra le résultat de l’évaluation du reste *)fun n -> if n < 2 then 1 else n * (fact (n - 1))(* le fact ci-dessus est le même que celui qu’on défini *)

27 / 104

Page 29: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Le typage

Le typage est une technique pour détecter automatiquement uneclasse d’erreurs de programmation:let x = 1 + 2 * 3

val x : int = 7

maislet x = 1 + "toto"

Characters 12-18:let x = 1 + "toto";;

^^^^^^Error: This expression has type string

but an expression was expected of type int

28 / 104

Page 30: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Limites du typage▶ Correct et bien typé:

let rec fact = fun n -> if n < 2 then 1 else fact(n - 1) * n

val fact : int -> int = <fun>

▶ Incorrect et mal typé:let rec fact = fun n -> if n < 2 then 1 else fact(n - "toto") * n

Characters 54-60:let rec fact = fun n -> if n < 2 then 1 else fact(n - "toto") * n

;;^^^^^^

Error: This expression has type stringbut an expression was expected of type int

▶ Incorrect mais bien typé:let rec fact = fun n -> if n < 2 then 1 else fact(n + 1) * n

val fact : int -> int = <fun>

29 / 104

Page 31: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

À quoi servent les types ?▶ à éviter segmentation fault

▶ les types capturent la structure de la mémoirelet x = 3 + "toto"

Characters 12-18:let x = 3 + "toto";;

^^^^^^Error: This expression has type string

but an expression was expected of type int

▶ à ne pas oublier de castype foo = A | Blet f x = match x with

| A -> 1

Characters 27-50:..........match x with

| A -> 1..Warning 8: this pattern-matching is not exhaustive.Here is an example of a value that is not matched:Btype foo = A | Bval f : foo -> int = <fun>

30 / 104

Page 32: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur

▶ les nombres▶ les fonctions▶ …

▶ les expressions réduites à un nom▶ les appels de fonction▶ les expressions conditionnelles▶ les expressions de filtrage

31 / 104

Page 33: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur▶ les nombres

▶ les fonctions▶ …

▶ les expressions réduites à un nom▶ les appels de fonction▶ les expressions conditionnelles▶ les expressions de filtrage

31 / 104

Page 34: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur▶ les nombres▶ les fonctions

▶ …▶ les expressions réduites à un nom▶ les appels de fonction▶ les expressions conditionnelles▶ les expressions de filtrage

31 / 104

Page 35: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur▶ les nombres▶ les fonctions▶ …

▶ les expressions réduites à un nom▶ les appels de fonction▶ les expressions conditionnelles▶ les expressions de filtrage

31 / 104

Page 36: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur▶ les nombres▶ les fonctions▶ …

▶ les expressions réduites à un nom

▶ les appels de fonction▶ les expressions conditionnelles▶ les expressions de filtrage

31 / 104

Page 37: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur▶ les nombres▶ les fonctions▶ …

▶ les expressions réduites à un nom▶ les appels de fonction

▶ les expressions conditionnelles▶ les expressions de filtrage

31 / 104

Page 38: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur▶ les nombres▶ les fonctions▶ …

▶ les expressions réduites à un nom▶ les appels de fonction▶ les expressions conditionnelles

▶ les expressions de filtrage

31 / 104

Page 39: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les catégories d’expressions

let rec fact = fun n -> if n < 2 then 1 else (fact (n - 1)) * n

▶ les expressions réduites à une valeur▶ les nombres▶ les fonctions▶ …

▶ les expressions réduites à un nom▶ les appels de fonction▶ les expressions conditionnelles▶ les expressions de filtrage

31 / 104

Page 40: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires

Page 41: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires : les nombres entiers

▶ valeurs dans [−230, 230 − 1] ou [−262, 262 − 1]

▶ type int▶ opérateurs principaux :

+ - * / mod

▶ exemple :let res = 5 / 2

val res : int = 2

33 / 104

Page 42: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires : les nombres flottants

▶ valeurs : 41.5, 24e5▶ type : float▶ opérateurs principaux :

+. -. *. /. **

▶ fonctions principales :sqrt log exp sin cos asin acos tan atan

▶ exemple :let res = 5. /. 2.

val res : float = 2.5

34 / 104

Page 43: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires : les booléens

▶ les 2 valeurs :true false

▶ type : bool▶ opérateurs principaux :

not && ||

▶ Attention: && et || sont évalués de gauche à droite

35 / 104

Page 44: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires : les caractères

▶ valeurs :'3' 'a' ';'

▶ type : char▶ opérations : voir cours sur la programmation impérative et

http://caml.inria.fr/pub/docs/manual-ocaml/libref/Char.html

36 / 104

Page 45: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires : les chaînes

▶ valeurs :"Hello World!"

▶ type : string▶ opérateurs principaux : ^ (concaténation), String.length▶ http://caml.inria.fr/pub/docs/manual-ocaml/

libref/String.html

37 / 104

Page 46: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires : l’unité

▶ unique valeur : ()▶ type : unit▶ utilisé comme type de retour des fonctions qui ne renvoient

rienlet res = print_endline

val res : string -> unit = <fun>

38 / 104

Page 47: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les valeurs élémentaires : les fonctions

▶ valeur de la forme fun nom -> expression

fun x -> 3 * x + 1

- : int -> int = <fun>

▶ type argument -> résultat▶ opérateur principal, l’application (dénoté par la juxtaposition)

(fun x -> 3 * x + 1) 5

- : int = 16

Ces fonctions sont anonymes. Pour leur donner un nom, on utiliseune définition:let mafonction = fun x -> 3 * x + 1

val mafonction : int -> int = <fun>

39 / 104

Page 48: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Comment lire le type des fonctions ?

Le parenthésage à droite est implicite dans l’expression du type desfonctions

int -> int -> int -> int=

int -> (int -> (int -> int))

Fonction qui prend un entier en argument, qui rend une fonctionqui prend un entier en argument, qui rend une fonction de entierdans entier.

40 / 104

Page 49: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fonctions : ordre supérieur

Une fonction est une valeur : elle peut être l’argument ou lerésultat d’autres fonction.Une fonctionnelle est une fonction acceptant en argument et/ourendant en résultat d’autres fonctions.

41 / 104

Page 50: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fonctionnelles : exercices

Soit la fonction sin : float → float▶ définir en Caml une fonction g

g : x 7→ sin xx

▶ définir en Caml une fonctionnelle hh : f 7→ (x 7→ f(x)

x )

42 / 104

Page 51: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fonctionnelles : solutions

let g = fun x -> (sin x)/.x

val g : float -> float = <fun>

let h = fun f -> (fun x -> (f x)/.x)

val h : (float -> float) -> float -> float = <fun>

let hs1 = h sin

val hs1 : float -> float = <fun>

(c’est la fonction sin(x)/x)let hs2 = fun x -> (h sin) x

val hs2 : float -> float = <fun>

(c’est évidemment la même fonction)

43 / 104

Page 52: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Valeurs composées : NUplets

Valeurs: (e1, e2, e3, ...)Type: (t1 * t2 * t3 * ...)

let triplet = (1, 1.2, true)

val triplet : int * float * bool = (1, 1.2, true)

let pair = fst((1,2+3),3)

val pair : int * int = (1, 5)

44 / 104

Page 53: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Conversions

int_of_float

- : float -> int = <fun>

float_of_int

- : int -> float = <fun>

int_of_char

- : char -> int = <fun>

45 / 104

Page 54: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Expressions

Page 55: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Définitions locales

let nom = expr1 in expr2

Sémantique1. on évalue expr1, qui donne val12. on évalue expr2 en ayant associé nom à val1

Exemplelet res =

let x = (11 + 10) in x + x

val res : int = 42

AttentionEn OCaml, let est utilisé à la fois pour introduire une phrase etpour introduire une définition locale

47 / 104

Page 56: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Définitions locales et séquentialité

Une utilisation courante des définitions locales est de choisir unordre d’évaluation.let p = (print_endline "Hello", print_endline "World")

WorldHelloval p : unit * unit = ((), ())

let p =let res1 = print_endline "Hello" inlet res2 = print_endline "World" in(res1,res2)

HelloWorldval p : unit * unit = ((), ())

48 / 104

Page 57: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Noms

Un nom est simplement un synonyme pour la valeur associée.L’évaluer revient à retourner cette valeur. Le type du nom est letype de la valeur.let x = 40 + 2

val x : int = 42

let res = x

val res : int = 42

49 / 104

Page 58: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Expressions conditionnelles (1)if expr1 then expr2 else expr3

Sémantique1. on évalue expr1, qui doit être de type booléen, en v12. selon v1, on évalue expr2 ou expr3, qui sont de même type

Exemples

let res = (if 3=4 then 2+7 else 7-7*2) + 4 val res : int = -3

let res = (if 3=4 then "foo" else 7-7*2) + 4

Characters 23-28:let res = (if 3=4 then "foo" else 7-7*2) + 4;;

^^^^^Error: This expression has type string

but an expression was expected of type int

50 / 104

Page 59: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Expressions conditionnelles (2)

On peut écrireif expr1 then expr2

qui est équivalent àif expr1 then expr2 else ()

=⇒ le type de expr2 doit être compatible avec unit

let res = if true then "foo"

Characters 23-28:let res = if true then "foo";;

^^^^^Error: This expression has type string

but an expression was expected of type unit

51 / 104

Page 60: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Le filtrage

Page 61: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Expressions de filtragematch expr with| motif1 -> expr1| motif2 -> expr2...| motifn -> exprn

SémantiqueOn évalue expr et sa valeur v est confrontée aux motifs.On évalue ensuite l’expression associée au premier motif quiaccepte la valeur v.Toutes les branches doivent retourner une valeur du même type.

Exemplelet res =

let b = false inmatch b with| true -> "foo"| false -> "bar"

val res : string = "bar"

53 / 104

Page 62: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Filtres de valeurs, filtre universel, combinaison▶ fitrage de valeur (true, "foo", 3, (), …): le motif

3

est « rigide », il accepte un seul élément, l’élément 3.▶ filtre universel (_): le motif

_

est un motif qui accepte tous les éléments▶ un filtre (m1,m2) accepte les paires (v1,v2) si m1 accepte v1

et m2 accepte v2. Par exemple,(true,_)

accepte toutes les paires dont le premier élément est true :(true,true)(true,55)(true,(4,5.67))...

54 / 104

Page 63: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Noms dans les motifs

Un nom dans un motif est un filtre universel qui est associe le nomà la valeur acceptée dans l’expression associéelet res =

match (1,2) with| (x,1) -> x (* ce motif n’accepte pas la valeur *)| (x,2) -> x + 10 (* valeur acceptée, x est associé à 1 *)| (_,_) -> 0

val res : int = 11

let sumpair = fun x ->match x with| (x1,x2) -> x1+x2

val sumpair : int * int -> int = <fun>

C’est une manière d’accéder aux éléments d’un nuplet

55 / 104

Page 64: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Noms dans les motifsAttentionlet x = 12

val x : int = 12

let egal_12 = fun n -> match n with| x -> true| _ -> false

Characters 50-51:| _ -> false;;

^Warning 11: this match case is unused.val egal_12 : 'a -> bool = <fun>

let res = egal_12 42

val res : bool = true

Un nom dans un motif n’est jamais remplacé par une valeur qui luiserait associée

56 / 104

Page 65: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Restrictions sur les motifs▶ une même variable ne peut apparaître qu’une seule fois par

motif: le motif doit être linéairelet diag p = match p with| (x,x) -> true| _ -> false

Characters 31-32:| (x,x) -> true

^Error: Variable x is bound several times in this matching

let diag p = match p with| (x,y) -> x=y

val diag : 'a * 'a -> bool = <fun>

▶ les valeurs acceptées par les motifs ne sont pas forcémentdisjointes

▶ le premier motif qui accepte la valeur est celui utilisé

57 / 104

Page 66: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Définitions et motifsLes définitions globale ou locale sont en fait de la formelet motif = expressionlet motif = expression in expression

On peut donc écrire :let (x,y) = (1+2, "foo" ^ "bar")

val x : int = 3val y : string = "foobar"

pour accéder aux éléments d’une paire;let () = print_endline "hello" (* filtrage rigide sur () *)

hello

si on sait que le résultat est ();let _ = 12

- : int = 12

si on veut ignorer le résultat.58 / 104

Page 67: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fonctions et motifs

Comme pour les définitions, les fonctions sont de la formefun motif -> expression

Exemplelet sumpair = fun (x1,x2) -> x1+x2

val sumpair : int * int -> int = <fun>

59 / 104

Page 68: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fonctions : combien d’arguments ?

▶ fonction à un argumentlet carre = fun x -> x*.x

val carre : float -> float = <fun>

▶ fonction à plusieurs arguments (?)let distance = fun (x,y) -> sqrt(carre(x)+.carre(y))

val distance : float * float -> float = <fun>

en fait un seul argument: un couple▶ la version à deux arguments:

let distance = fun x -> fun y -> sqrt(carre(x)+.carre(y))

val distance : float -> float -> float = <fun>

60 / 104

Page 69: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Syntaxe des fonctionsUne fonction à un argumentlet nom = fun x -> expr

peut s’écrirelet nom x = expr

De la même manière, une fonction attendant une pairelet sumpair = fun (x1,x2) -> x1+x2

peut s’écrirelet sumpair (x1,x2) = x1+x2

Enfin, une fonction à deux argumentslet foo = fun x -> fun y -> expr

peut s’écrirelet foo x y = expr

(et pareil pour 3, 4, … arguments)61 / 104

Page 70: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Application d’une fonction à plusieurs argumentsAppliquer une fonction = remplacer x par 3(fun x -> fun y -> x + y) 3

devient(fun y -> 3 + y)

C’est une nouvelle fonction. On parle alors d’application partielle.let f = fun x -> let _ = print_endline "argument 1" in

fun y -> let _ = print_endline "argument 2" inx + y

let _ = print_endline "avant"let res1 = f 3let _ = print_endline "après"let res2 = res1 4

avantargument 1aprèsargument 2val f : int -> int -> int = <fun>val res1 : int -> int = <fun>val res2 : int = 7

62 / 104

Page 71: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Les fonctions retardent l’exécutionÉvaluer l’expressionfun () -> print_endline "Hello"

retourne immédiatement la fonction mais ne l’exécute pas. Lafonction sera exécuté à chaque fois qu’elle sera appelée.En revanche, évaluer l’expressionprint_endline "Hello"

affiche Hello et retourne ().let foo () = print_endline "Hello"let _ = foo ()let _ = foo ()

HelloHelloval foo : unit -> unit = <fun>

let foo = print_endline "Hello"let _ = foolet _ = foo

Helloval foo : unit = () 63 / 104

Page 72: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exhaustivité

Soit la définition :let trait_dir dir = match dir with| "nord" -> 0| "sud" -> 1| "est" -> 2| "ouest" -> 3

quel est le comportement de Caml ?

Characters 20-94:....................match dir with| "nord" -> 0| "sud" -> 1| "est" -> 2| "ouest" -> 3..

Warning 8: this pattern-matching is not exhaustive.Here is an example of a value that is not matched:""val trait_dir : string -> int = <fun>

64 / 104

Page 73: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exhaustivité

Soit la définition :let trait_dir dir = match dir with| "nord" -> 0| "sud" -> 1| "est" -> 2| "ouest" -> 3

quel est le comportement de Caml ?Characters 20-94:

....................match dir with| "nord" -> 0| "sud" -> 1| "est" -> 2| "ouest" -> 3..

Warning 8: this pattern-matching is not exhaustive.Here is an example of a value that is not matched:""val trait_dir : string -> int = <fun>

64 / 104

Page 74: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

La fonction et logique

et : bool * bool -> bool

x y et (x,y)true true truetrue false falsefalse true falsefalse false false

let et (x,y) = match (x,y) with| (true,true) -> true| (true,false) -> false| (false,true) -> false| (false,false) -> false

val et : bool * bool -> bool = <fun>

65 / 104

Page 75: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (1)Imaginer une définition de la fonction et plus concise

let et (x,y) = match (x,y) with| (true,y) -> if y then true else false| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match (x,y) with| (true,y) -> y| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match x with| true -> y| false -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = if x then y else false

val et : bool * bool -> bool = <fun>

66 / 104

Page 76: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (1)Imaginer une définition de la fonction et plus conciselet et (x,y) = match (x,y) with| (true,y) -> if y then true else false| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match (x,y) with| (true,y) -> y| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match x with| true -> y| false -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = if x then y else false

val et : bool * bool -> bool = <fun>

66 / 104

Page 77: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (1)Imaginer une définition de la fonction et plus conciselet et (x,y) = match (x,y) with| (true,y) -> if y then true else false| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match (x,y) with| (true,y) -> y| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match x with| true -> y| false -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = if x then y else false

val et : bool * bool -> bool = <fun>

66 / 104

Page 78: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (1)Imaginer une définition de la fonction et plus conciselet et (x,y) = match (x,y) with| (true,y) -> if y then true else false| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match (x,y) with| (true,y) -> y| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match x with| true -> y| false -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = if x then y else false

val et : bool * bool -> bool = <fun>

66 / 104

Page 79: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (1)Imaginer une définition de la fonction et plus conciselet et (x,y) = match (x,y) with| (true,y) -> if y then true else false| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match (x,y) with| (true,y) -> y| (false,y) -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = match x with| true -> y| false -> false

val et : bool * bool -> bool = <fun>

let et (x,y) = if x then y else false

val et : bool * bool -> bool = <fun>

66 / 104

Page 80: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Filtrages particuliers

▶ Combinaison de motifslet trait_caract c = match c with| 'a' | 'e' | 'i' | 'o' | 'u' | 'y' -> "voyelle"| _ -> "pas voyelle"

▶ Filtrage d’intervalle de caractèreslet f c = match c with| 'a' .. 'z' -> "lettre"| _ -> "pas lettre"

▶ Nommage de la valeur filtrée, <motif> as <nom>let maj c = match c with| ('a'..'z' as l) -> char_of_int (int_of_char l - 32)| x -> x

67 / 104

Page 81: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (2)Supposons donnée une fonction:val f : int -> int * int * int = <fun>

Écrire une fonction de typeval g : int -> bool = <fun>

telle que:▶ g x = true si le triplet f x contient au moins un zéro,▶ g x = false sinon.

let g x = match f x with| (0,_,_) -> true| (_,0,_) -> true| (_,_,0) -> true| _ -> false

let g x = match f x with| (0,_,_) | (_,0,_) | (_,_,0) -> true| _ -> false

68 / 104

Page 82: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (2)Supposons donnée une fonction:val f : int -> int * int * int = <fun>

Écrire une fonction de typeval g : int -> bool = <fun>

telle que:▶ g x = true si le triplet f x contient au moins un zéro,▶ g x = false sinon.

let g x = match f x with| (0,_,_) -> true| (_,0,_) -> true| (_,_,0) -> true| _ -> false

let g x = match f x with| (0,_,_) | (_,0,_) | (_,_,0) -> true| _ -> false

68 / 104

Page 83: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice de filtrage (2)Supposons donnée une fonction:val f : int -> int * int * int = <fun>

Écrire une fonction de typeval g : int -> bool = <fun>

telle que:▶ g x = true si le triplet f x contient au moins un zéro,▶ g x = false sinon.

let g x = match f x with| (0,_,_) -> true| (_,0,_) -> true| (_,_,0) -> true| _ -> false

let g x = match f x with| (0,_,_) | (_,0,_) | (_,_,0) -> true| _ -> false

68 / 104

Page 84: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

begin et endLes filtrages imbriqués peuvent poser problèmelet bug b g = match b with

| true ->match g with| "foo" -> 1| _ -> 0

| false -> -1

Characters 93-98:| false -> -1;;

^^^^^Error: This pattern matches values of type bool

but a pattern was expected which matches values of type string

let bug b g = match b with| true -> begin

match g with| "foo" -> 1| _ -> 0

end| false -> -1

val bug : bool -> string -> int = <fun>

69 / 104

Page 85: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

begin et endLes filtrages imbriqués peuvent poser problèmelet bug b g = match b with

| true ->match g with| "foo" -> 1| _ -> 0

| false -> -1

Characters 93-98:| false -> -1;;

^^^^^Error: This pattern matches values of type bool

but a pattern was expected which matches values of type string

let bug b g = match b with| true -> begin

match g with| "foo" -> 1| _ -> 0

end| false -> -1

val bug : bool -> string -> int = <fun>

69 / 104

Page 86: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Polymorphisme & Inférence detypes

Page 87: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Le polymorphisme

certaines fonctions peuvent être appliquées à des arguments dontle type n’est pas tout le temps le même : fonctions génériques oupolymorpheslet first (x,y) = x

val first : 'a * 'b -> 'a = <fun>

let _ = first (3, "foo")

- : int = 3

let _ = first (true, first)

- : bool = true

71 / 104

Page 88: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Variables de type

les parties génériques du type sont représentées par des variablesde type notées 'a, 'b, …

▶ first:- : 'a * 'b -> 'a = <fun>

▶ doublon:let doublon x = (x,x)

val doublon : 'a -> 'a * 'a = <fun>

▶ un changement de structurelet chg_struct ((x,y),z) = (y,(x,z))

val chg_struct : ('a * 'b) * 'c -> 'b * ('a * 'c) = <fun>

72 / 104

Page 89: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice : polymorphisme

Définir la fonction identitéval id : 'a -> 'a = <fun>

qui renvoie son argument, et la fonction de compositionval comp : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b = <fun>

qui prend en argument une paire de fonction (f,g) et rend lafonction composée

let id x = x

let comp (f,g) = fun x -> f (g x)

oulet comp (f,g) x = f (g x)

73 / 104

Page 90: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice : polymorphisme

Définir la fonction identitéval id : 'a -> 'a = <fun>

qui renvoie son argument, et la fonction de compositionval comp : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b = <fun>

qui prend en argument une paire de fonction (f,g) et rend lafonction composéelet id x = x

let comp (f,g) = fun x -> f (g x)

oulet comp (f,g) x = f (g x)

73 / 104

Page 91: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exercice : polymorphisme

Définir la fonction identitéval id : 'a -> 'a = <fun>

qui renvoie son argument, et la fonction de compositionval comp : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b = <fun>

qui prend en argument une paire de fonction (f,g) et rend lafonction composéelet id x = x

let comp (f,g) = fun x -> f (g x)

oulet comp (f,g) x = f (g x)

73 / 104

Page 92: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Inférence de type

OCaml devine les types, et utilise cette information pour compilerle programme.let add x y = x + y

val add : int -> int -> int = <fun>

n’est pas compilé commelet addf x y = x +. y

val addf : float -> float -> float = <fun>

C’est pour cela que l’on distingue + et +..

74 / 104

Page 93: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Récursivité

Page 94: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Factorielle

▶ définition intuitive: fact n = 1 * 2 * … * n▶ définition mathématique:

fact(n) = 1 si n < 2

fact(n) = n ∗ fact(n − 1) si n ≥ 2

▶ en OCamllet rec fact n = if n < 2 then 1 else n * (fact (n-1))

val fact : int -> int = <fun>

let _ = fact 5

- : int = 120

76 / 104

Page 95: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Calcul de factoriellePour calculer e1 * e2, on calcul d’abord e1, puis on calcule e2,puis on multiplie les résultats

fact 55 * (fact 4)5 * (4 * (fact 3))5 * (4 * (3 * (fact 2)))5 * (4 * (3 * (2 * (fact 1))))5 * (4 * (3 * (2 * 1)))5 * (4 * (3 * 2))5 * (4 * 6)5 * 24120

Lors de l’appel récursif à fact, on doit garder de l’informationpour les calculs à faire après

77 / 104

Page 96: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fonctions récursives

Une définition récursive valide comporte au moins 2 cas :▶ un ou plusieurs cas de base (où figure un élément particulier)

if n < 2 then 1

▶ un ou plusieurs cas récursifs, utilisant la fonction en cours dedéfinitionelse n * (fact (n-1))

Attention l’appel récursif doit « se rapprocher » du cas de base.Sinon: risque de boucle infinielet rec fact = fun n -> if n < 2 then 1 else n * (fact (n+1))

78 / 104

Page 97: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Anatomie d’une fonction récursivelet rec funrec arg =

if arg > 4 then 0 (* cas de base *)else (* cas récursif *)

(* code exécuté avant l’appel récursif *)let _ = Printf.printf "avant, arg = %d\n" arg in(* appel récursif, il faut se souvenir de arg pour après *)let res = funrec (arg + 1) in(* retour de l’appel récursif, on peut utiliser res et arg *)Printf.printf "après, arg = %d, res = %d\n" arg res;(* valeur finale retournée *)(res + 10)

let res = funrec 1

avant, arg = 1avant, arg = 2avant, arg = 3avant, arg = 4après, arg = 4, res = 0après, arg = 3, res = 10après, arg = 2, res = 20après, arg = 1, res = 30val funrec : int -> int = <fun>val res : int = 40

79 / 104

Page 98: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Graphiquement

Code

Avant (arg)Récursion

Après (arg)

Exécution

Avant (1)

Avant (2)

Avant (3)

Avant (4)

Après (4)

Après (3)

Après (2)

Après (1)

80 / 104

Page 99: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Mini guide de traduction

int power(int v, int n) {int res = 1;while (n > 0) {res = res * v;n = n - 1;

}return res;

}

let power v n =let rec aux res curn =

if curn > 0 thenlet res' = res * v inlet curn' = curn - 1 inaux res' curn'

elseres

in aux 1 n

val power : int -> int -> int = <fun>

let rec power v n =if n = 0 then 1else v * (power v (n-1))

val power : int -> int -> int = <fun>

81 / 104

Page 100: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Mini guide de traduction

int power(int v, int n) {int res = 1;while (n > 0) {res = res * v;n = n - 1;

}return res;

}

let power v n =let rec aux res curn =

if curn > 0 thenlet res' = res * v inlet curn' = curn - 1 inaux res' curn'

elseres

in aux 1 n

val power : int -> int -> int = <fun>

let rec power v n =if n = 0 then 1else v * (power v (n-1))

val power : int -> int -> int = <fun>

81 / 104

Page 101: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Récursion terminale

Si on se souvient de trop de choses, on tombe en panne demémoirelet rec stupide n = if n <= 0 then 0 else 1 + (stupide (n-1))let res = stupide 265000

Stack overflow during evaluation (looping recursion?).

Si on retourne directement le résultat de l’appel récursif, alorsOCaml optimise et ne se souviens plus des argumentslet rec malin n acc =

if n <= 0 then acc else let acc' = acc + 1 in malin (n-1) acc'let res = malin 265000 0

val malin : int -> int -> int = <fun>val res : int = 265000

82 / 104

Page 102: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Récursion terminale

Si on se souvient de trop de choses, on tombe en panne demémoirelet rec stupide n = if n <= 0 then 0 else 1 + (stupide (n-1))let res = stupide 265000

Stack overflow during evaluation (looping recursion?).

Si on retourne directement le résultat de l’appel récursif, alorsOCaml optimise et ne se souviens plus des argumentslet rec malin n acc =

if n <= 0 then acc else let acc' = acc + 1 in malin (n-1) acc'let res = malin 265000 0

val malin : int -> int -> int = <fun>val res : int = 265000

82 / 104

Page 103: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Domaines de récursion

▶ cas classique: la récurrence sur les entiers▶ cas de base pour 0▶ valeur en n+1 calculée avec la valeur pour n

▶ listes▶ cas de base pour la liste vide▶ valeur pour l’ajout d’un élément calculé avec la valeur pour le

reste de la liste▶ arbres, etc …

83 / 104

Page 104: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exemple

U0 = 4

Un = 2Un−1 + 3n pour n > 0

let rec u x = if x = 0 then 4 else 2 * u (x-1) + 3 * xlet res = u 10

val u : int -> int = <fun>val res : int = 10204

Version avec récursion terminalelet urt x =

let rec aux acc n =if n > x then accelse let acc' = 2 * acc + 3 * n in

aux acc' (n+1)in aux 4 1

let res = urt 10

val urt : int -> int = <fun>val res : int = 10204

84 / 104

Page 105: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Récursivité croisée

let rec nom1 = expr1and nom2 = expr2

Les expressions expr1 et expr2 peuvent utiliser nom1 et nom2.let rec pair n = if n = 0 then true else impair (n-1)and impair n = if n = 0 then false else pair (n-1)

val pair : int -> bool = <fun>val impair : int -> bool = <fun>

85 / 104

Page 106: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Spécificités de Caml

Page 107: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Opérateurs de comparaison

= <> < > <= >=

let _ = "foo" = "foo"

- : bool = true

let _ = "foo" <> "foo"

- : bool = false

let _ = "foo" < "bar"

- : bool = false

let _ = "foo" > "foo"

- : bool = false

Attention L’opérateur « == » existe mais il ne faut pas l’utiliser.

87 / 104

Page 108: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Divers : les priorités en Caml (1)

L’application est notée par la simple juxtaposition de la fonction etde son argument.expr expr

Une suite d’applications est parenthésée par défaut à gauche.expr expr expr

est équivalent à(expr expr) expr

88 / 104

Page 109: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Divers : les priorités en Caml (2)

priorités décroissantes1. application: f x2. opérateur arithmétiques: f x + 1 est (f x) + 13. construction de n-uplets: f x + 1,2 est ((f x) + 1),24. abstraction: fun x -> f x + 1,2 est fun x -> (((f x) +

1),2)Ne pas hésiter à mettre des parenthèsesL’opérateur - est par défaut la soustraction et pas l’opposé: f -1est « f moins un ». Pour appliquer une fonction f à -1 il fautécrire f (-1).

89 / 104

Page 110: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Curryfication

Comparer et typer les définitions :let f (x,y) = x + 2*y

let g x y = x + 2*y

let _ = f (4,5)

- : int = 14

let _ = g 4 5

- : int = 14

90 / 104

Page 111: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Curryfication

▶ f doit toujours être appelée avec une paire d’entiers commeargument

▶ g peut être appelée avec un entier ou deux▶ g 4 est la fonction fun y -> 4 + 2*y

91 / 104

Page 112: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Application partielle

let compdbl f x = f (f x)

val compdbl : ('a -> 'a) -> 'a -> 'a = <fun>

let square x = x*x

val square : int -> int = <fun>

compdbl square 5

- : int = 625

let puiss4 = compdbl square

val puiss4 : int -> int = <fun>

92 / 104

Page 113: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Un exemple

Page 114: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fonctionnelle d’itération

Ecrire une fonctionnelle qui correspond à la sémantique del’itération pour

▶ caractérisation à partir d’exemples de l’itération « pour »▶ établissement des lois de récurrence▶ écriture de la fonctionnelle repeter▶ constat de l’efficacité de cette fonctionnelle

94 / 104

Page 115: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Exemples d’itérations

1. calcul itératif de 2n

2. calcul itératif du terme de rang n de la suite▶ u0 = 3▶ un = 3 ∗ un−1 + 5

3. calcul itératif du terme de rang n de la suite de fibonacci▶ u0 = 0▶ u1 = 1▶ un = un−1 + un−2

95 / 104

Page 116: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

La boucle classique

puiss := 1 initpour i:=1 à n faire

puiss := puiss*2 f

U := 3 initpour i:=1 à n faire

U := U*3+5 f

96 / 104

Page 117: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

La sémantique de toute itération (1)

Similitudes:▶ utilisation d’une variable v de cumul (U , puiss)▶ initialisation de v▶ le contenu de la variable subit à chaque pas une

transformation v := f(v)▶ f(x) = x*2 pour 2n

▶ f(x) = x*3+5 pour la suite Un

97 / 104

Page 118: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

La sémantique de toute itération (2)

Schéma général

x := x0pour i := 1 à n faire

x := f(x)

La valeur à rendre est x. Elle dépend de x0, n et f.On cherche F telle que x = F(n, f, x0)

98 / 104

Page 119: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

La sémantique de toute itération (3)

valeur de x en fonction de x0, n et f :n = 0 x = F(0, f, x0) = x0n = 1 x = F(1, f, x0) = f(x0)n = 2 x = F(2, f, x0) = f(f(x0))

…cas général: x = F(n, f, x0) = fn(x0)

99 / 104

Page 120: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

La loi de récurrence

F(n, f, x0) = fn(x0) = f(fn−1(x0)) = f(F(n − 1, f, x0))

F est en fait la fonctionnelle repeter▶ repeter n f x0 = x0 pour n = 0▶ repeter n f x0 = f (repeter (n-1) f x0) pour n > 0

100 / 104

Page 121: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

La fonctionnelle repeter

let rec repeter f x0 n =if n = 0 then x0 else f (repeter f x0 (n-1))

val repeter : ('a -> 'a) -> 'a -> int -> 'a = <fun>

101 / 104

Page 122: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Utilisation de repeterUtiliser l’itérateur repeter pour calculer

▶ 2n

▶ le terme de rang n de la suite▶ u0 = 3▶ un = 3 ∗ un−1 + 5

let puissde2 n = repeter (fun x -> x*2) 1 n

val puissde2 : int -> int = <fun>

let suite n = repeter (fun x -> 3*x+5) 3 n

val suite : int -> int = <fun>

On peut utiliser l’application partielle pour ne pas mentionner nlet puissde2 = repeter (fun x -> x*2) 1

val puissde2 : int -> int = <fun>

let suite = repeter (fun x -> 3*x+5) 3

val suite : int -> int = <fun>

102 / 104

Page 123: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fibonacci itératif

Revenons à Fibonacci

U := 0; V := 1;pour i:=2 à n faire

Y := V;V := V+U;U := Y;

let fibo n = snd (repeter (fun (x,y) -> (x+y,x)) (1,0) n)

val fibo : int -> int = <fun>

103 / 104

Page 124: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Fibonacci itératif

Revenons à Fibonacci

U := 0; V := 1;pour i:=2 à n faire

Y := V;V := V+U;U := Y;

let fibo n = snd (repeter (fun (x,y) -> (x+y,x)) (1,0) n)

val fibo : int -> int = <fun>

103 / 104

Page 125: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Cumuler les termes d’une suite

Définirsigma(n) =

n∑i=0

Ui

en organisant les calculs de façon à diminuer la complexité.

acc:=0;pour i:=0 à n faire

acc:=s+Ui

let sigma n =snd(repeter

(fun (t,acc) -> (3*t+5,acc+t))(3,0)(n+1))

val sigma : int -> int = <fun>

104 / 104

Page 126: OCaml : un Langage Fonctionnel · On peut tout programmer en OCaml La plupart des langages sont Turing complets. Les langages sont des outils. Un bon outil est un outil adapté au

Cumuler les termes d’une suite

Définirsigma(n) =

n∑i=0

Ui

en organisant les calculs de façon à diminuer la complexité.

acc:=0;pour i:=0 à n faire

acc:=s+Ui

let sigma n =snd(repeter

(fun (t,acc) -> (3*t+5,acc+t))(3,0)(n+1))

val sigma : int -> int = <fun>

104 / 104