• Aucun résultat trouvé

n’implique pas l’´evaluation de l’expression de d´efinition n+1. Par contre, le fait que n soit li´e montre que cette derni`ere expression pourra ˆetre effective- ment ´evalu´ee lorsque l’identificateurnsera associ´e `a une valeur effective, dans une expression d’application de fonction par exemple (ce point sera revu au chapitre 5, section 5.3)

Remarque: la discussion qui pr´ec`ede montre que l’identification d’un argu- ment formel n’a aucune importance : les deux phrases

let successeur n = n + 1 ;; et

let successeur p = p + 1 ;;

d´efinissent exactement la mˆeme valeur fonctionnelle2. Dans la premi`ere expres-

sion, l’argument formelnest li´e dans l’expression de d´efinitionn + 1. Dans la deuxi`eme expression, l’argument formelpest li´e dans l’expression de d´efinition p + 1. Par contre, la phrase

let f n = p + 1

d´efinit une autre valeur fonctionnelle, car l’identificateur pn’est pas li´e dans le contexte localn ~?de la valeur fonctionnelle. Plusieurs situations sont alors possibles :

1. Si p est d´ej`a li´e `a une valeur de type int dans le contexte lorsque la d´efinition de la valeur fonctionnelle fest rencontr´ee, alors fd´enote une fonction constante : la correspondance qui, `a toute valeur de n, associe la valeur enti`ere de l’expression de d´efinition p + 1, ind´ependante de n. 2. Sipest d´ej`a li´ee dans le contexte, mais `a une valeur d’un type autre que

int, l’expression de d´efinitionp+1est incoh´erente, donc in´evaluable. 3. Sip n’est pas li´ee dans le contexte, l’expression de d´efinition p+1 n’est

pas ´evaluable.

4.3

Fonctions `a plusieurs arguments

4.3.1 Fonctions `a deux arguments

Reprenons l’exemple du calcul du prix ttc. Nous venons de voir comment faire abstraction du prix h.t. dans le calcul du prix ttc lorsque le taux de tva est

fix´e `a la valeur particuli`ere 18.6%. Supposons maintenant que nous voulions

exprimer le mˆeme calcul, mais avec un taux de tva diff´erent, par exemple 5.5%.

2. ce ph´enom`ene n’est pas unique : on le rencontre aussi, par exemple dans le cadre des fractions o`u deux notations telles que 1

2 et 4

Nous pouvons d´efinir une autre fonction, `a savoir la fonction de calcul du prix ttc des articles soumis `a la tva 5.5% :

# let pttc 55 x = x +. 0.055*.x ;;

pttc 55:float -> float = <fun>

Ainsi, `a la valeur de type float 0.186correspond une fonction de type float ->float (identifi´ee par pttc 186), `a la valeur de type float 0.055 corres- pond une autre fonction de typefloat ->float(identifi´ee par pttc 55). Plus g´en´eralement, `a chaque valeur taux de type float, repr´esentant un taux de tva, on peut faire correspondre une fonction de type float ->float, expri- mant l’algorithme de calcul du prix ttc des articles soumis `a la tva de taux taux. En faisant abstraction des valeurs particuli`eres de taux de tva, on d´efinit une fonction qui, `a une valeur de typefloat(le taux de tva) fait correspondre une fonction de typefloat ->float (la fonction de calcul du prix ttc pour ce taux de tva). Une telle fonction est donc une entit´e de type float ->(float ->float). Il s’agit l`a d’un exemple de fonction dont le r´esultat est de type fonctionnel.

La machine CAML va confirmer cette analyse, comme le montre la d´efinition de la fonctionpttc ci-dessous :

# let pttc taux x = x +. taux*.x ;;

pttc:float -> float -> float = <fun>

Dans sa r´eponse, la machine CAML ne met pas de parenth`eses dans l’expres- sion de type depttc: le constructeur de type-> est associatif `a droite, ce qui

signifie tout simplement que le parenth´esage suivant est implicite : float ->float ->float signifie float ->(float ->float) et, plus g´en´eralement :

t1 ->t2 ->...->tnsignifie t1 ->(t2 ->(...->tn) ...).

Les fonctions pttc 186ou pttc 55d´efinies plus haut peuvent ˆetre d´efinies comme des applications de la fonctionpttc`a des valeurs particuli`eres de l’ar- gument formeltaux:

# let pttc 186 = pttc 0.186 ;;

pttc 186:float-> float = <fun>

# pttc 186 167. ;;

-:float = 198.062

r´esultat que l’on pourrait obtenir directement sans passer par l’identifica- teur interm´ediaire pttc 186 :

# pttc 0.186 167. ;; (* signifiant (pttc 0.186) 167. *)

4.3. Fonctions `a plusieurs arguments 43 # let pttc 55 = pttc 0.055 ;;

pttc 55:float -> float = <fun>

# pttc 55 167. ;;

-:float= 176.185

La fonction pttc que nous venons de d´efinir est bien une fonction `a un argument (de typefloat), dont le r´esultat est une fonction, elle mˆeme `a un argument de typefloat et `a r´esultat de typefloat. En fait, la fonctionpttc peut aussi ˆetre vue, conceptuellement, comme une fonction `a deux arguments de typefloatet `a r´esultat de typefloat, puisque l’expression finale exprimant l’algorithme de calcul :x +. taux*.x, d´epend de deux “param`etres”, `a savoir le taux de tva taux et le prix h.t. x. Lorsque l’on “fixe” le premier des deux arguments (en l’occurrence le taux de tvataux), on obtient une fonction `a un argument, c’est-`a-dire dans laquelle l’expression finale exprimant le r´esultat ne d´epend plus que d’un param`etre, le prix hors taxex.

Cette vision de la fonction pttc comme fonction `a deux arguments est manifeste dans une expression comme pttc 0.186 167. o`u, pour obtenir un r´esultat du type primitif float, il faut former une expression comportant l’identificateur de la fonction suivi de deux expressions (deux arguments ef- fectifs). Toutefois, comme nous venons de le voir, il est possible de ne fournir qu’un seul argument effectif, et dans ce cas, le r´esultat est une fonction. 4.3.2 Fonctions `a t arguments ou `a un argument t-uple

Les constructions fonctionnelles du paragraphe 4.3 peuvent ´evidemment ˆetre g´en´eralis´ees `a un nombre quelconque d’arguments. Par exemple, la fonc- tion ci-dessous d´elivre le maximum de 3 nombres r´eels, `a partir du maximum de deux nombres r´eels :

# let max2 x y = if x>=.y then x else y ;;

max2: float -> float -> float = <fun>

# let max3 x y z = max2 (max2 x y) z ;;

max3:float -> float -> float -> float

et on pourrait tout aussi bien obtenir le maximum de 4 nombres : # let max4 x y z t = max2 (max2 x y) (max2 z t) ;;

max4:float -> float -> float -> float -> float = <fun>

Une autre mani`ere de d´efinir les fonctions max2, max3, max4serait de les consid´erer comme des fonctions `a un seul argument, de type respectif couple (2-uple), triplet (3-uple), quadruplet (4-uple) :

# let maxi2 (x, y) = if x>=.y then x else y ;;

maxi2:(float*float) -> float =<fun>

# let maxi3 (x, y, z) = maxi2 ((maxi2(x, y), z) ;;

maxi3:(float*float*float) -> float

# let maxi4 (x, y, z, t) = maxi2((maxi2(x,y)), maxi2(z,t)) ;;

maxi4:(float*float*float*float) -> float

La diff´erence entre les deux fonctions max2 et maxi2, par exemple, ne r´eside pas dans l’algorithme lui-mˆeme (l’expression de d´efinition est identique) mais

essentiellement dans le typage. La premi`ere,max2, est une fonction `a un argu- ment de typefloat et `a r´esultat fonctionnel - pouvant aussi ˆetre vue comme une fonction `a deux arguments de type float et `a r´esultat de type float, tandis que la seconde, maxi2, est une fonction `a un seul argument de type couple float*float, et `a r´esultat non fonctionnel. Cette diff´erence de typage se fait ´evidemment sentir dans la forme des expressions utilisant ces fonctions, comme on le voit en comparant les expressions de d´efinition des deux fonctions max3etmaxi3 ou max4 etmaxi4.

Nous n’insisterons pas ici sur les subtilit´es “conceptuelles” de ces deux formes, signalant seulement que l’on peut facilement d´efinir l’une des deux fonctions `a partir de l’autre :

(* max2 ´etant d´efinie : *)

# let maxi2 (x, y) = max2 x y ;;

maxi2:(float*float) -> float = <fun>

(* maxi2 ´etant d´efinie : *)

# let max2 x y = maxi2(x, y) ;;

max2:float -> float -> float = <fun>

Pour la “culture”, indiquons que la forme `a r´esultat fonctionnel (comme max2) est appel´ee la forme curryfi´ee de la forme `a r´esultat non fonctionnel (comme maxi2), l’adjectif curryfi´e ´etant d´eriv´e du nom du logicien Haskell CURRY, qui a ´etudi´e l’´equivalence de ces formes fonctionnelles.

Nous avons finalement le sch´ema syntaxique suivant (figure 4.1 compl´etant la partie d´efinition du sch´ema de la figure 3.6.