TD n 3 Rappel : let est le mot réservé utilisé pour définir la valeur d une variable ou d une fonction. Dans l expression suivante : #let x = 10; val x: int =10 let x génère l interprétation val x: Dans cette expression l identificateur x est suivi du caractère =,nous sommes donc dans le cas ou il s agit de la définition d une variable. Ici il s agit de la variable entière x qui prend pour valeur 10 Dans l expression suivante : #let f a = a+1; val f: int int = <fun> let f génère l interprétation val f: Dans cette expression l identificateur f est suivi de l identificateur a avant le caractère =,nous sommes donc dans le cas ou il s agit de la définition d une fonction f dont l argument est a. Ici il s agit de définir la fonction entière f qui a pour argument l entier a. Le résultat de la fonction est un entier car dans le corps de la fonction on réalise une somme d entiers à l aide de l opérateur + réservé aux entiers.
Exercice 1 1.1 / Indiquez l'interprétation de l expression suivante : # let fc a b c d = a b c + if d = (0,0) then b c else c;; Décomposition de l interprétation let fc a b c d =... Définition de la valeur de la fonction fc dotée des 4 arguments a b c et d, ceci est déduit de l apparition des arguments a b c d présents après let fc et avant = val fc : «type de a»->«type de b»->«type de c»->«type de d»->«type de fc» = <fun> let fc a b c d = a b c +... La fonction fc calcule une somme d entiers, ceci est déduit de l apparition de l opérateur +, son résultat est donc un entier. Mise à jour du type de fc val fc : «type de a»->«type de b»->«type de c»->«type de d»-> int = <fun> let fc a b c d = a b c +... Dans a b c + on constate que a est une fonction dotée des 2 arguments b et c Le résultat de la fonction a doit être un entier car il est utilisé dans une somme d entiers. Mise à jour du type de a val fc : («type de b»->«type de c»-> int )->«type de b»->«type de c»->«type de d»-> int = <fun> let fc a b c d = a b c + if d = (0,0) then b c else... Dans + if d = (0,0) then b c on constate que b est une fonction dotée de l argument c Le résultat de la fonction b doit être un entier car il est utilisé dans une somme d entiers.. Mise à jour du type de b val fc : ( («type de c»-> int)->«type de c»-> int )->(«type de c»-> int)->«type de c»->«type de d»-> int = <fun> let fc a b c d = a b c + if d = (0,0) then b c else c;; Dans else c c est un entier car il est utilisé dans une somme d entiers. Mise à jour du type de c val fc : ( ( int -> int) -> int -> int ) -> ( int -> int) -> int ->«type de d»-> int = <fun> let fc a b c d = a b c + if d = (0,0) then b c else c;; Dans d = (0,0) d est un couple d entiers car il est comparé à (0,0) Mise à jour du type de d val fc : ( ( int -> int) -> int -> int ) -> ( int -> int) -> int -> int * int -> int = <fun> En résumé nous avons les types suivants : fc ( ( int -> int) -> int -> int ) -> ( int -> int) -> int -> int * int -> int a ( ( int -> int) -> int -> int ) b ( int -> int) c int d int * int Solution let fc a b c d = a b c + if d = (0,0) then b c else c;; val fc : ( ( int -> int) -> int -> int ) -> ( int -> int) -> int -> int * int -> int = <fun> Exemples let f2 x = 2*x;; val f2 : int -> int =<fun> let f1 f2 x = f2 x +10;; val f1 : ( a -> int) -> a -> int =<fun> fc f1 f2 20 (0,0);; - : int = 90 Le calcul réalisé est (f1 f2 20) + (f2 20) ((f2 20) + 10) + (f2 20) 40+10 + 40 90
1.2 / Comment interpréter les évaluations suivantes et donner un exemple de code correspondant. a/ val f : int -> int -> 'a -> ('a -> int) -> int = <fun> Méthode : Pour une fonction f on analyse Le type du résultat de la fonction Il s agit du dernier type présent avant le caractère = <fun> Les arguments de la fonction La présence de parenthèses indique que nous sommes en présence d un argument qui est une fonction. On conviendra de nommer les fonctions rencontrées f1 f2.. fn. En l absence de parenthèses les arguments sont de type simple. On conviendra de nommer ces arguments a b c... val f : int -> int -> 'a -> ('a -> int) -> int = <fun> Donne l entête de fonction f suivante en application de la méthode proposée précédemment. let f a b c f1 = int = <fun> f est de type int exemple de calcul let f a b c f1 =. +.;; int -> int a et b sont de type int exemple de calcul let f a b c f1 = a*b +.;; 'a -> ('a -> int) c est de type indéterminé, il est nécessairement argument de la fonction f1 dont le résultat est de type int exemple de calcul let f a b c f1 = a*b + f1 c;; let f a b c f1 = a * b + f1 c ;; val f : int -> int -> 'a -> ('a -> int) -> int = <fun> b/ val f : 'a -> ('a -> 'a) -> 'b -> ('a -> ('a -> 'a) -> 'b) -> bool = <fun> Donne l entête de fonction f suivante en application de la méthode proposée précédemment. let f a f1 b f2 = bool = <fun> f est de type bool avec des arguments de type indéterminés qui peuvent être distincts exemple de calcul let f a f1 b f2 =. &&.;; 'a -> ('a -> 'a) a est de type indéterminé 'a, il doit être argument de la fonction f1 dont le résultat est de même type que a exemple de calcul let f a f1 b f2 = (a = f1 a) &&.;; 'b b est de type indéterminé 'b ('a -> ('a -> 'a) -> 'b) la fonction f2 a pour argument a et f1. Son résultat est de même type que b exemple de calcul let f a f1 b f2 = (a = f1 a) && (b = f2 a f1);; let f a f1 b f2 = (a = f1 a) && (b = f2 a f1) ;; val f : 'a -> ('a -> 'a) -> 'b -> ('a -> ('a -> 'a) -> 'b) -> bool = <fun>
Exercice 2 Etant donnée la définition :f g h x y z = g x y && h y z 1 / Proposer des définitions de g et de h Interprétation de la fonction let f g h x y z = g x y && h y z ;; f : ('a -> 'b -> bool) -> ('b -> 'c -> bool) -> 'a -> 'b -> 'c -> bool = <fun> Les contraintes : g et h sont des fonctions booléennes dans la fonction f le deuxième argument de la fonction g et également le premier argument de la fonction h g est une fonction booléenne dotée de 2 arguments let g a b = a < b ;; g : 'a -> 'a -> bool = <fun> h est une fonction booléenne dotée de 2 arguments let h a b = a mod b > 0 ;; h : int -> int -> bool = <fun> Soient g et h ainsi définies, dans l appel f g h x y z;; y et z, arguments de h, doivent être des entiers dans la fonction h on calcule y mod z si y est un entier x doit être un entier dans la fonction g dans la fonction g on compare x et y : x<y Exemples f g h 15 17 4;; f g h 15 16 4;; -: bool = false f g h 18 17 4;; -: bool = false 2 / Quelle est la nature de f g h? Appel incomplet de la fonction f il manque 3 arguments qui, dans le contexte, sont des entiers. f g h est une fonction booléenne qui attends trois arguments de type entiers f g h ;; - : int -> int -> int -> bool = <fun> let nf = f g h ;; val nf : int -> int -> int -> bool = <fun> nf 15 17 4;; f g h 15 17 4;;
3 / Evaluer : f (fun x y -> x > y) (fun x y -> x * x > y) 4 (-3) 5 f (fun x y -> x > y) (fun x y -> x * x > y) 4 (-3) 5;; dans (fun x y -> x > y) qui définit g -> x a pour valeur 4 y a pour valeur -3 dans (fun x y -> x *x > y) qui définit h -> x a pour valeur -3 y a pour valeur 5 Le calcul réalisé est : 4 > -3 && (-3 * -3) > 5 Expressions équivalentes let g a b = a>b;; val g : 'a -> 'a -> bool = <fun> let h c d = c*c > d;; val h : int -> int -> bool = <fun> f g h 4 (-3) 5;; - : bool = true Le calcul réalisé est : g 4 (-3) && h (-3) 5 4 > -3 && (-3 * -3) > 5 Exercice 3 Ecrire une fonction admettant deux arguments, une fonction et une variable qui permet d'appliquer la fonction f deux fois à l élément x f o f (x). let double f x = f (f x) ;; val double : ('a -> 'a) -> 'a -> 'a = <fun> La fonction double doit avoir pour premier argument une fonction dont l argument est de même type que son résultat. Appliquer le résultat à une fonction de votre choix let g x = x + 2 ;; g : int -> int = <fun> double g 4 ;; - : int = 8 Peut-on l appliquer à la fonction de l exercice 1 de la semaine précédente? Oui car l argument de la fonction est de même type que son résultat. let f (x,y) = (x+y, x*y) ;; val f : int * int -> int * int = <fun> double f (2,3) ;; - : int * int = (11, 30)
Exercice 4 Ecrire une fonction dont l argument est entier et qui retourne un booléen indiquant si l entier est le carré d un entier. Solution let f x = val f : int -> bool = <fun> Exemples f 25 ;; - : bool = true f 24 ;; - : bool = false f(-4) ;; - : bool = false f 0 ;; - : bool = true if x >=0 then let a = int_of_float (sqrt (float_of_int x)) in a *a = x else false;; Exercice 5 Pour les coefficients c1 c2 et c3 écrire une fonction dont le résultat est la moyenne pondérées des notes n1 n2 et n3. On proposera deux solutions en utilisant ou non des n-uplets Solution avec 6 arguments dont 3 coefficients c1 c2 et c3 et 3 notes n1 n2 et n3. let f c1 c2 c3 n1 n2 n3 = (n1 *. c1 +. n2 *. c2 +. n3 *. c3) /. (c1 +. c2 +. c3) ;; val f : float->float->float -> float->float->float -> float = <fun> f 1. 2. 7. 8. 10. 12. ;; - : float = 11.2 Solution avec 2 arguments dont un triplet de coefficients et un triplet de notes. let g (c1,c2,c3) (n1,n2,n3) = (n1 *. c1 +. n2 *. c2 +. n3 *. c3) /. (c1 +. c2 +. c3) ;; val g : float*float*float -> float*float*float -> float = <fun> g (1.,2.,7.) (8.,10.,12.) ;; - : float = 11.2 Appel incomplet Si on réalise l appel incomplet suivant g (1.,2.,7.) on définit une fonction dotée du triplet de coefficients (1.,2.,7.) qui attend le deuxième argument manquant, c est à dire un triplet de notes. let m = g(1.,2.,7.);; val m : float*float*float -> float = <fun> m (8.,10.,12.) ;; - : float = 11.2 m (16.,10.,12.) ;; - : float = 12.