Laboratoire 04: Fonctions d'ordre supérieur
Les fonctions d’ordre supérieur sont des fonctions paramétrées par une ou plusieurs fonctions et/ou qui renvoient une fonction. Le but de ce TP est d’utiliser et d’écrire de telles fonctions et de se familiariser avec cette notion.
Premières fonctions d’ordre supérieures et curryfication
Dans cet exercice, on utilisera les deux définitions suivantes :
let square (x : int) : int = x * x
let my_list = [3; 12; 3; 40; 6; 4; 6; 0]
- Exprimer le type de la fonction
f_sumparamétrée par une fonction f ainsi que deux entiers a et b et qui calcule f(a) + f(b).
- Écrire la fonction
f_sum.
# f_sum square 2 3;;
- : int = 13
# f_sum (fun x -> x + 1) 2 3;;
- : int = 7
-
Redéfinir la fonction
f_sumen utilisant exclusivement le mot cléfunction. -
Lier aux noms
f1,f2,f3,f4etf5des définitions de fonctions de sorte à vérifier les types suivants.
val f1 : int -> int -> int = <fun>
val f2 : (int -> int) -> int = <fun>
val f3 : (int -> int) -> int -> int = <fun>
val f4 : (int -> int) -> (int -> int) = <fun>
val f5 : ((int -> int) -> int) -> int = <fun>
Rappel : les parenthèses dans les expressions de types portant sur les flèches ->
associent vers la droite. Ainsi, le type t1 -> (t2 -> t3) est équivalent au
type t1 -> t2 -> t3.
- Sans définir de nouvelle fonction et en utilisant la fonction
squarede manière appropriée, créer la liste des carrés des éléments demy_list. Utiliser la fonctionList.map.
- : int list = [9; 144; 9; 1600; 36; 16; 36; 0]
- Sans définir de nouvelle fonction et en utilisant la multiplication (attention, il
y a une astuce à suivre pour transformer l’opérateur
*en fonction) de manière appropriée, créer la liste des doubles des éléments demy_list.
- : int list = [6; 24; 6; 80; 12; 8; 12; 0]
-
Exprimer le type de la fonction
make_listsachant qu’elle est paramétrée par une fonctionmake(dont l’unique paramètre est de typeunit) et un entiernet qui renvoie une liste denéléments fabriqués avec la fonctionmake. -
Écrire la fonction
make_list.
# let f () = 0;;
val f : unit -> int = <fun>
# make_list f 8;;
- : int list = [0; 0; 0; 0; 0; 0; 0; 0]
-
En utilisant
make_listet la fonction appropriée du moduleRandom, créer une liste de 64 booléens générés aléatoirement. Il est possible d’utiliserRandom.bool ()pour engendrer aléatoirement un booléen de manière équiprobable. -
En utilisant
make_listet une fonction anonyme, créer une liste de 16 entiers (compris entre 0 et 127) générés aléatoirement. Il est possible d’utiliserRandom.int npour engendrer aléatoirement et de manière équiprobable un entier compris entre0etn - 1.
Sur une ligne
Dans cet exercice, on utilisera les définitions suivantes :
let entiers = [2; 5; 7; 3; 12; 4; 9; 2; 11];;
let animaux = ["Wombat"; "aXolotl"; "pangolin"; "suricate"; "paresseuX"; "quokka"; "lemurien"];;
Toutes les expressions demandées par les descriptions suivantes doivent être sous la forme
d’appels de fonctions d’ordre supérieur du module List (comme List.map, List.for_all, List.filter, List.fold_left, etc.). Il est interdit de définir de nouvelles fonctions non anonymes.
Note: penser à consulter la documentation des modules List, Char et String.
Écrire de telles expressions pour :
- calculer la liste des longueurs des chaînes de caractères de la liste
animaux;
- : int list = [6; 7; 8; 8; 9; 6; 8]
- calculer la liste de tous les animaux de la liste
animauxécrits en majuscules ;
- : string list = ["WOMBAT"; "AXOLOTL"; "PANGOLIN"; "SURICATE"; ...]
- calculer la liste des chaînes de la liste
animauxqui sont écrites en minuscules ;
- : string list = ["pangolin"; "suricate"; "lemurien"]
- calculer la liste des noms des
animauxde longueurs paires ;
- : string list = ["Wombat"; "pangolin"; "suricate"; "quokka"; "lemurien"]
- calculer la liste suivante, construite à partir de la liste
entiers;
- : (int * string) list = [(2, "pair"); (5, "impair"); (7, "impair");
(3, "impair"); (12, "pair"); (4, "pair"); (9, "impair"); (2, "pair");
(11, "impair")]
- calculer une liste de listes composées de
nfois la valeur den, pour chaque entierndans la listeentiers;
- : int list list = [[2; 2]; [5; 5; 5; 5; 5]; [7; 7; 7; 7; 7; 7; 7]; [3; 3; 3];
[12; 12; 12; 12; 12; 12; 12; 12; 12; 12; 12; 12]; [4; 4; 4; 4]; ... ]
-
tester s’il existe une élément de la liste
animauxqui commence par le caractère's'; -
tester si tous les éléments de la liste
animauxsont de longueur congrue à 2 modulo 5.
Replis
Écrire les fonctions suivantes de sorte à avoir un corps de fonction qui tienne sur une seule ligne et utilise des fonctions d’ordre supérieur :
-
sum lqui renvoie la somme des éléments d’une liste d’entiersl; -
size lqui renvoie la longueur d’une listel; -
last lqui renvoie le dernier élément d’une listelnon vide ; -
nb_occ e lqui renvoie le nombre d’occurrences d’un élémentedansl; -
max_list lqui renvoie le maximum de la listelnon vide ; -
average lqui renvoie la moyenne (de typefloat) des nombres entiers de la listel. Il est interdit d’utilisersizeetsum.
Rappel : la plupart de ces fonctions ont été implantées sans utiliser de fonctions d’ordre supérieur lors du labo 3
Prédicats sur les listes
Un prédicat est une fonction qui teste si une propriété est vérifiée par son paramètre (et renvoie donc un booléen). Par exemple :
# let is_even = fun x -> x mod 2 = 0;;
val is_even : int -> bool = <fun>
# is_even 0, is_even 1, is_even 2;;
- : bool * bool * bool = (true, false, true)
-
Écrire la fonction
my_for_allparamétrée par un prédicatpet une listelet qui teste si tous les éléments delvérifientp. Comme contraintes, cette fonction ne doit rien utiliser du moduleList(autre que l’opérateur de construction::et bien sûr la liste vide[]). -
Écrire la fonction
my_for_all2qui fait la même chose quemy_for_allmais qui utilise la fonctionfold_leftdu moduleList. -
Si ce n’est pas déjà fait, réécrire la fonction
my_for_all2sans utiliser la fonctionmapdu moduleList. -
Écrire la fonction
my_for_all3qui fait la même chose quemy_for_allmais qui utilise la fonctionfold_rightdu moduleList. -
Écrire la fonction
my_existsparamétrée par un prédicatpet une listelet qui teste s’il existe un élément delvérifiantp. Cette fonction doit respecter les contraintes exposées dans la question surmy_for_all. -
Écrire la fonction
noneparamétrée par un prédicatpet une listelet qui teste si aucun des éléments de la liste ne vérifiep. Cette fonction doit respecter les contraintes exposées dans la question surmy_for_all. -
Écrire la fonction
not_allparamétrée par un prédicatpet une listelet qui teste s’il existe un élément delne vérifiant pasp. Cette fonction doit respecter les contraintes exposées dans la question surmy_for_all. -
Écrire la fonction
orderedparamétrée par un prédicat binairepet une liste \([a_1; \dots; a_n]\) et qui teste si toutes les expressions \(p~a_i~ a_{i + 1}\) sont vraies pour tout \(1 \leq i \leq n - 1\).
# ordered (<) [1; 2; 3];;
- : bool = true
# ordered (<) [1; 4; 3];;
- : bool = false
# ordered (fun x y -> x + y >= 1) [1; 4; -3; 6];;
- : bool = true
# ordered (fun x y -> x + y >= 1) [1; 4; -5; 6];;
- : bool = false
- Écrire la fonction
filter2paramétrée par un prédicat binairepet deux listes \([a_1; \dots; a_n]\) et \([b_1; \dots; b_n]\) et qui renvoie la liste des couples \((a_i, b_i)\) tels que l’expression \(p~a_i~ b_i\) est vraie.
# filter2 (<) [2; 2; 3] [1; 4; 5];;
- : (int * int) list = [(2, 4); (3, 5)]
Génération exhaustive de permutations
Une permutation d’une liste l est une liste l' qui contient les mêmes
éléments que ceux de l mais dans un ordre potentiellement différent.
Écrire une fonction perm l qui renvoie la liste de toutes les permutations de la liste
l.
# perm [1;2];;
- : int list list = [[1; 2]; [2; 1]]
# perm [1;2;3];;
- : int list list =
[[1; 2; 3]; [2; 1; 3]; [2; 3; 1]; [1; 3; 2]; [3; 1; 2]; [3; 2; 1]]
# perm [1;2;3;4];;
- : int list list =
[[1; 2; 3; 4]; [2; 1; 3; 4]; [2; 3; 1; 4]; [2; 3; 4; 1]; [1; 3; 2; 4];
[3; 1; 2; 4]; [3; 2; 1; 4]; [3; 2; 4; 1]; [1; 3; 4; 2]; [3; 1; 4; 2];
[3; 4; 1; 2]; [3; 4; 2; 1]; [1; 2; 4; 3]; [2; 1; 4; 3]; [2; 4; 1; 3];
[2; 4; 3; 1]; [1; 4; 2; 3]; [4; 1; 2; 3]; [4; 2; 1; 3]; [4; 2; 3; 1];
[1; 4; 3; 2]; [4; 1; 3; 2]; [4; 3; 1; 2]; [4; 3; 2; 1]]