introduction à Caml

publicité
1/30
Chapitre 0 : Le langage Caml
Programmation impérative versus fonctionnelle
Prog. impérative
séquences d’instructions ;
notion d’état du programme ;
boucles for et while essentielles.
les processeurs sont de nature impérative : exécutions d’instructions
données par « op codes ».
état du programme : contenu de la mémoire à chaque instant.
Python, C, Assembleur, Langage machine : plus ou moins haut
niveaux, mais tous impératifs.
2/30
Programmation impérative versus fonctionnelle
Prog. fonctionnelle
autre paradigme de programmation ;
un programme est une fonction mathématique ;
exécution du programme : évaluation de la fonction ;
Eviter la notion d’état, d’effet de bord : un calcul donne toujours le
même résultat (c.ex : fonction de tri en Python)
la récursivité (appel d’une fonction à elle même) remplace les
boucles.
3/30
Exemple : la factorielle
Factorielle impérative
Fonction fact(n)
f ← 1;
pour i allant de 1 à n faire faire
f ←f ×i
fin
Renvoyer f
Factorielle fonctionnelle
Fonction fact(n)
si n ≥ 0 alors
Renvoyer 1
sinon
Renvoyer n × fact(n − 1)
fin
4/30
Python versus Caml
Python
Langage impératif, permettant l’usage de la récursivité.
Caml
Langage fonctionnel, permettant la programmation impérative.
5/30
Introduction à Caml
Un langage fortement typé
; présentation de l’interpréteur : 4+1 ;;
Caml : fortement typé.
un calcul Caml termine par ;;
Caml procède (avant l’évaluation) par une analyse de type.
Mélange des genres interdit !
notion de polymorphisme (exemple : max).
avantages/inconvénients
plus dur d’écrire des choses fausses ;
un peu plus long à écrire que Python.
6/30
Types simples
Unit
type unit
équivalent du None de Python. Une seule valeur : ().
# () ;;
- : unit = ()
Entiers
type int
sur 64 bits, plage de valeurs [[−262 , 262 − 1]].
opérateurs usuels : +, *, -, / (division entière) et mod (modulo).
#
#
-
7/30
2*16 ;;
: int = 32
58 mod 14 ;;
: int = 2
Types simples
Flottants
type float ;
semblables à ceux de Python ;
opérateurs simples : les mêmes que pour les entiers (sauf mod qui n’a
pas d’équivalent), mais suivis d’un point : +., /., -., *. ;
fonctions usuelles (cos, sin, exp, atan...) définies sur les flottants ;
exponentiation (**).
#
#
#
-
8/30
2.0 *. 8.9 ;;
: float = 17.8
2.0 ** 8.9 ;;
: float = 477.712891667
cos 5. ;;
: float = 0.283662185463
Types simples
Pas de mélanges !
# 2 * 3.0 ;;
Toplevel input:
>2 * 3.0 ;;
>
^^^
This expression has type float,
but is used with type int.
# 2 ** 5 ;;
Toplevel input:
>2 ** 5 ;;
>^
This expression has type int,
but is used with type float.
9/30
Types simples
Booléens
type bool ;
deux constantes : true et false ;
opérateurs : && (et logique), || (ou logique, la barre s’obtient avec
Alt gr + 6) et not (non logique).
#
#
#
-
true && false ;;
: bool = false
false || true ;;
: bool = true
not true ;;
: bool = false
paresseux, comme en Python :
#
#
10/30
false && 1/0>0 ;;
: bool = false
true || 1/0>0 ;;
: bool = true
Déclarations
Déclaration « globale »
let x= ... ;; pour déclarer une variable.
plutôt une constante...
# let x = 4 ;;
x : int = 4
Déclaration « locale »
let x= ... in ... ;; pour déclarer une variable localement.
si x déja liée, valeur précédente oubliée (temporairement) ;
affectation locale à ce qui suit in ;
#
#
-
11/30
let x= 5.**0.25 in x +. x *. x +. x ** 3. ;;
: float = 7.0751182836
x ;;
: int = 4
Déclarations
Déclaration « simultanée »
let x= ... and y= ... ;; pour déclarer deux variables
simultanément ;
compatible avec in ;
#
x
y
#
-
let x=0
: int =
: int =
let x=0
: int =
and y=1 ;;
0
1
and y=1 in x+y ;;
1
ne pas confondre locale et simultanée.
# let x=0 and y=x+2 in x+y ;;
Toplevel input:
>let x=0 and y=x+2 in x+y ;;
>
^
The value identifier x is unbound.
12/30
Déclarations : références
Références
variables Caml : liaison d’un nom et d’une valeur ;
référence : « pointeur » vers une case mémoire dont on peut lire et
écrire le contenu ;
la « valeur » de la référence est une adresse mémoire (fixée)
la valeur « pointée » par la référence est modifiable
syntaxe : ref valeur pour créer une référence pointant initialement
vers valeur.
type t ref, où t est le type de la valeur.
typique de la programmation impérative !
# let r= ref 0 ;;
r : int ref = ref 0
13/30
Déclarations : références
Déférencement, modification
valeur pointée par une référence !r ;
modifier la valeur : r := x.
#
x
#
#
-
14/30
let x= ref 0 ;;
: int ref = ref 0
x:= !x + 1 ;;
: unit = ()
!x ;;
: int = 1
Types plus complexes
Tuples
n-uplet
type : produit cartésien des types
syntaxe : parenthèses facultatives et virgules
# (true, 0, atan 1.0) ;;
- : bool * int * float = true, 0, 0.785398163397
déconstruction : let a,b,... = t
# let a,b=(0, 1.0) ;;
a : int = 0
b : float = 1.0
fst et snd : renvoie première et deuxième composante d’un couple.
#
#
15/30
fst (1, 5.0) ;;
: int = 1
snd (4, true) ;;
: bool = true
Types plus complexes
Tableaux
taille fixée à la création : immuable ;
homogène !
type t vect où t est le type des éléments.
#
#
-
[|5; 0; 7|] ;;
: int vect = [|5; 0; 7|]
[|(2,1) ; (5,7)|] ;;
: (int * int) vect = [|2, 1; 5, 7|]
si n la taille, t.(0), ..., t.(n-1) : accès aux éléments ;
modification : t.(i) <- x
#
t
#
#
-
let t = [|0; 5; 7|] ;;
: int vect = [|0; 5; 7|]
t.(0) <- 2 ;;
: unit = ()
t ;;
: int vect = [|2; 5; 7|]
programmation impérative !
16/30
Types plus complexes
Chaînes de caractères
type string
très similaire à des char vect
accès/modification : s.[i]
attention : char 6= string.
#
s
#
#
#
-
17/30
let s = "abc" ;;
: string = "abc"
s.[0] ;;
: char = `a`
s.[0] <- `d` ;;
: unit = ()
s ;;
: string = "dbc"
Fonctions
Quelques exemples
#
#
#
#
-
18/30
int_of_float ;;
: float -> int = <fun>
int_of_float (3.5) ;;
: int = 3
fst ;;
: 'a * 'b -> 'a = <fun>
fst (true, 5.4) ;;
: bool = true
Fonctions
Quelques exemples
#
#
#
#
-
int_of_float ;;
: float -> int = <fun>
int_of_float (3.5) ;;
: int = 3
fst ;;
: 'a * 'b -> 'a = <fun>
fst (true, 5.4) ;;
: bool = true
Fonctions
une fonction est une valeur
type : t1 -> t2 ;
18/30
Fonctions à un seul argument. Appel
Syntaxe
function variable -> expression
types de la variable et de l’expression détectés automatiquement
# function x -> x+1 ;;
- : int -> int = <fun>
Appel
comme en mathématiques : f (x) ;
en fait les parenthèses sont facultatives : f x.
x de type t1 et f de type t1 -> t2 alors f x de type t2.
polymorphisme !
Exemples
#
#
19/30
(function x -> x +. 1.) 2. ;;
: float = 3.0
let f = function x -> x+1 in f 5 ;;
: int = 6
Fonctions à un seul argument + liaison
Syntaxe
Pour déclarer et lier une fonction à une variable ;
let f x = expression
20/30
Fonctions à un seul argument + liaison
Syntaxe
Pour déclarer et lier une fonction à une variable ;
let f x = expression
Exemple 1
#
f
#
-
20/30
let f x = x+1 ;;
: int -> int = <fun>
f 5 ;;
: int = 6
Fonctions à un seul argument + liaison
Syntaxe
Pour déclarer et lier une fonction à une variable ;
let f x = expression
Exemple 1
#
f
#
-
let f x = x+1 ;;
: int -> int = <fun>
f 5 ;;
: int = 6
Exemple 2 : fonction sur un couple
#
f
#
-
20/30
let f
: int
f (0,
: int
(x,y) = x+y ;;
* int -> int = <fun>
2) ;;
= 2
Fonctions à un seul argument + liaison
Exemple 3 : polymorphisme
#
f
#
-
21/30
let f (x,y) = (y, x) ;;
: 'a * 'b -> 'b * 'a = <fun>
f (2, 3.0) ;;
: float * int = 3.0, 2
Fonctions à un seul argument + liaison
Exemple 3 : polymorphisme
#
f
#
-
let f (x,y) = (y, x) ;;
: 'a * 'b -> 'b * 'a = <fun>
f (2, 3.0) ;;
: float * int = 3.0, 2
Exemple 4 : avec déclaration locale
#
f
#
-
21/30
let f x = let y= exp x in (y+. 1.0/. y)/. 2. ;;
: float -> float = <fun>
f 1.0 ;;
: float = 1.54308063482
Fonctions à un seul argument + liaison
Exemple 3 : polymorphisme
#
f
#
-
let f (x,y) = (y, x) ;;
: 'a * 'b -> 'b * 'a = <fun>
f (2, 3.0) ;;
: float * int = 3.0, 2
Exemple 4 : avec déclaration locale
#
f
#
-
let f x = let y= exp x in (y+. 1.0/. y)/. 2. ;;
: float -> float = <fun>
f 1.0 ;;
: float = 1.54308063482
Exemple 5 : déclaration simultanée
# let ch x
and sh
ch : float
sh : float
21/30
= let y= exp x in (y+. 1.0/. y)/. 2.
x = let y= exp x in (y-. 1.0/. y)/. 2.;;
-> float = <fun>
-> float = <fun>
Notion de curryfication
Bijetion naturelle
F(E1 , E2 ) : applications de E1 dans E2 ;
F(E × F , G) : applications de E × F dans G ;
F(E , F(F , G)) : applications de E dans F(F , G) ;
22/30
Notion de curryfication
22/30
Bijetion naturelle
F(E1 , E2 ) : applications de E1 dans E2 ;
F(E × F , G) : applications de E × F dans G ;
F(E , F(F , G)) : applications de E dans F(F , G) ;
bijection naturelle !
ϕ : F(E × F , G) →
f
7−→
F(E , F(F , G))
x→
7 (y 7→ f (x , y ))
Forme curryfiée / non-curryfiée
f ∈ F(E × F , G) : forme non curryfiée ;
f ∈ F(E , F(F , G)) : forme curryfiée ;
intérêt des formes curryfiées : fonctions partielles !
se généralise à F(E1 × · · · × En , G)
Type et appels d’une fonction curryfiée
Type
t_1 * t_2 -> t : non curryfiée
t_1 -> (t_2 -> t) : curryfiée
Caml omet les parenthèses : t_1 -> t_2 -> t.
23/30
Type et appels d’une fonction curryfiée
Type
t_1 * t_2 -> t : non curryfiée
t_1 -> (t_2 -> t) : curryfiée
Caml omet les parenthèses : t_1 -> t_2 -> t.
Appel d’une fonction curryfiée
si f : t1 -> t2 -> t et x de type t1, f x a le type t2 -> t ;
si y de type t2, (f x) y a le type t ;
parenthèses inutiles, priorité à la fonction : f x y
généralisation : f x1 x2 x3 ... xn
23/30
Exemples Caml
Exemple 1 : max
#
#
#
-
24/30
max ;;
: 'a -> 'a -> 'a = <fun>
max 20 ;;
: int -> int = <fun>
max 20 58 ;;
: int = 58
Exemples Caml
Exemple 1 : max
#
#
#
-
max ;;
: 'a -> 'a -> 'a = <fun>
max 20 ;;
: int -> int = <fun>
max 20 58 ;;
: int = 58
Exemple 2 : make_vect
#
#
-
24/30
make_vect ;;
: int -> 'a -> 'a vect = <fun>
make_vect 5 0 ;;
: int vect = [|0; 0; 0; 0; 0|]
Exemples Caml
Exemple 1 : max
#
#
#
-
max ;;
: 'a -> 'a -> 'a = <fun>
max 20 ;;
: int -> int = <fun>
max 20 58 ;;
: int = 58
Exemple 2 : make_vect
#
#
-
make_vect ;;
: int -> 'a -> 'a vect = <fun>
make_vect 5 0 ;;
: int vect = [|0; 0; 0; 0; 0|]
Exemple 3 : sub_vect
#sub_vect ;;
- : 'a vect -> int -> int -> 'a vect = <fun>
#sub_vect [| 1.0; 2.0; 3.0; 4.0; 5.0; 6.0; 7.0 |] 2 4 ;;
- : float vect = [|3.0; 4.0; 5.0; 6.0|]
24/30
Création de fonctions curryfiées
Méthode 1 : function
# function x -> (function y -> x+y) ;;
- : int -> int -> int = <fun>
25/30
Création de fonctions curryfiées
Méthode 1 : function
# function x -> (function y -> x+y) ;;
- : int -> int -> int = <fun>
Méthode 2 : fun
#
#
-
25/30
fun x y -> x+y ;;
: int -> int -> int = <fun>
(fun x y -> x+y) 1 6 ;;
: int = 7
Création de fonctions curryfiées
Méthode 1 : function
# function x -> (function y -> x+y) ;;
- : int -> int -> int = <fun>
Méthode 2 : fun
#
#
-
fun x y -> x+y ;;
: int -> int -> int = <fun>
(fun x y -> x+y) 1 6 ;;
: int = 7
Méthode 3 avec liaison
# let somme x y = x+y ;;
somme : int -> int -> int = <fun>
# somme 1 6 ;;
- : int = 7
25/30
Création de fonctions curryfiées
Méthode 1 : function
# function x -> (function y -> x+y) ;;
- : int -> int -> int = <fun>
Méthode 2 : fun
#
#
-
fun x y -> x+y ;;
: int -> int -> int = <fun>
(fun x y -> x+y) 1 6 ;;
: int = 7
Méthode 3 avec liaison
# let somme x y = x+y ;;
somme : int -> int -> int = <fun>
# somme 1 6 ;;
- : int = 7
Généralisation
Déclaration + liaison : let f x1 x2 ... xn = expression
25/30
Expressions conditionnelles en Caml
if then else
if cond then a else b
cond expression booléenne ;
a et b expressions de même type
type de l’expression = type commun à a et b.
Exemple
# if true then 1 else 0 ;;
- : int = 1
# 1+(if true then 1 else 0) ;;
- : int = 2
# if true then 1.0 else 2 ;;
Toplevel input:
>if true then 1.0 else 2 ;;
>
^
This expression has type int,
but is used with type float.
26/30
Expressions conditionnelles en Caml
Quelques subtilités
pas de else équivalent à else ()
# if true then print_string "c'est vrai !" ;;
c'est vrai !- : unit = ()
27/30
Expressions conditionnelles en Caml
Quelques subtilités
pas de else équivalent à else ()
# if true then print_string "c'est vrai !" ;;
c'est vrai !- : unit = ()
en Caml, séquence d’instructions séparées par des points-virgules ;
une seule instruction dans les blocs if, else ou utilisation de
begin ... end.
# if true then x:=1 ; print_string "Exécuté ?" ;;
Exécuté ?- : unit = ()
# if false then x:=1 ; print_string "Exécuté ?" ;;
Exécuté ?- : unit = ()
# if false then begin x:=1 ; print_string "Exécuté ?" end ;;
- : unit = ()
27/30
Boucles
boucle for
for i = i1 to i2 do instructions done.
i prend les valeurs de i1 à i2 (inclus) ;
si i2 < i1 pas d’exécution ;
corps de boucle : instructions, séparées par des point-virgules, de
type unit
type de la boucle : unit.
pas de modification du compteur de boucle !
variante : for i = i1 downto i2 do instructions done
28/30
Boucles
Exemple de boucle for : factorielle
let fact n=
let y=ref 1 in
for i=1 to n do
y:= !y * i
done ;
!y
;;
29/30
Boucles
boucle while
similaire : while cond do instructions done
mêmes restrictions
Exemple de boucle while : Euclide
let pgcd a b=
let x=ref a and y=ref b in
while !y > 0 do
let r= !x mod !y in
x:= !y ;
y:= r
done ;
!x ;;
30/30
Téléchargement