-
LUMINEAU NICOLAS authoredLUMINEAU NICOLAS authored
- TP5: Parcours génériques de structure et projets dune
- 1. Manipulations de listes à l'aide de fonctions génériques
- 1.1. Utilisation des fonctions sur les listes
- 1.2 Recodage de fonctions sur les listes
- 2. Arbre n-aires: recodage
- 2.1. Recodage de quelques fonctions de base avec la bibliothèque standard OCaml
- 2.2. Gestion d'option, fold et minimum
TP5: Parcours génériques de structure et projets dune
1. Manipulations de listes à l'aide de fonctions génériques
On considère les fonctions suivantes prédéfinies en OCaml:
-
List.map: ('a -> 'b) -> 'a list -> 'b list
Cette fonction transforme une liste en utilisant la fonction passée en paramètre pour transformer les éléments un par un. AinsiList.map f [x1; x2; x3; ... ]
renverra une liste égale à[f x1; f x2; f x3; ... ]
. -
List.filter: ('a -> bool) -> 'a list -> 'a list
Cette fonction transforme une liste en utilisant la fonction passée en paramètre conserver uniquement certains éléments. AinsiList.filter f [x1; x2; x3; ... ]
renverra une liste contenant exatctement lesxi
pour lesquelsf xi
vauttrue
. -
List.for_all: ('a -> bool) -> 'a list -> bool
Cette fonction indique si une fonction renvoie vrai pour tous les éléments d'une liste. AinsiList.for_all f [x1; x2; x3; ... ]
renvoietrue
si pour tous lesxi
, on af xi
vauttrue
.
1.1. Utilisation des fonctions sur les listes
En utilisant List.map
, coder les fonctions suivantes:
- Une fonction
f1
qui prend une liste d'int
et renvoie la liste de leur représentation sous forme destring
. - Une fonction
f2
qui prend unint
x
et une liste d'int
l
et renvoie la liste transformée en multipliant chaque élément del
parx
. - Une fonction
f3
qui prend deuxint
x
ety
et une liste d'int
l
et renvoie la liste (debool
) indiquant pour chacun des éléments del
s'il est bien compris entrex
ety
.
Bien tester vos fonctions avec assert
.
En utilisant List.filter
, coder les fonctions suivantes:
- Une fonction
f4
qui prend deuxint
x
ety
et une liste d'int
l
et renvoie la liste des éléments del
qui sont compris entrex
ety
. - Une fonction
f5
qui prend une liste de liste d'int
et renvoie la liste sans les (sous-)listes vides.
Bien tester vos fonctions avec assert
.
En OCaml, on peut voir une opérateur comme une fonction en le plaçant tout seul entre parenthèses. Ainsi (!=)
est une fonction qui prend deux arguments et renvoie true
si il sont égaux. Ainsi (!=) 1 2
revoie true
, alors que (!=) 1 1
renvoie false
.
Recoder la fonction f5
sans le mot clé fun
en utilisant une application partielle de (!=)
.
On peut bien sûr combiner List.map
et List.filter
.
Coder une fonction f6
qui prend une liste d'int option
l
et renvoie une liste d'int
contenant les valeurs int
contenues dans l
. Par exemple, f6 [ Some 3; None; Some 18; Some 42; None; Some 37; None]
vaudra [3; 18; 42; 37]
.
1.2 Recodage de fonctions sur les listes
Recoder List.map
, List.filter
et List.for_all
.
2. Arbre n-aires: recodage
Dans cet exercice, on reprend les fonctionnalités développées dans la section 1. du TP4, mais en les recodant avec les fonctions déjà fournies avec OCaml.
Remarque: en OCaml on peut écrire fun x y -> ...
à la place de fun x -> fun y -> ...
.
2.1. Recodage de quelques fonctions de base avec la bibliothèque standard OCaml
Reprendre le type
'a arbre_n
du TP4, section 1.1
On pourra reprendre les tests écrits lors du TP4.
Recoder la fonction
hauteur_arbre
sans utiliserhauteur_foret
, mais en appelant directementList.map
etList.fold_left
pour extraire les hauteurs des arbres fils et trouver la hauteur maximale parmi celles-ci.
Recoder
list_of_arbre_aux
en utilisantList.fold_right
pour remplacer les appels àlist_of_foret
. Encapsulerlist_of_arbre_aux
avec unlet ... in ...
dans la définition delist_of_arbre
. On écrira lelet
avant de prendre l'argument delist_of_arbre
.
2.2. Gestion d'option, fold et minimum
Pour gérer proprement le calcul du minimum, on va s'équiper d'un décorateur lift_option_2
ayant le comportement suivant. Soit f: 'a -> 'a -> 'a
. On suppose que g = lift_option_2 f
. Alors g
aura le type 'a option -> 'a -> 'a option
. Si le premier argument de g
est None
, alors g
renvoie Some x
si x
est son second argument. Sinon g
renvoie Some (f y x)
où y
est la valeur contenue dans son premier argument et x
est son second argument.
Définir
lift_option_2
en commençant par préciser son type. Tester avecassert
en passant la fonctionmin
àlift_option_2
.
On veut à présent définir fold_left_arbre
qui aggrège une valeur via un accumulateur à la manière de List.fold_left
, mais en parcourant un arbre et pas une liste.
Définir le type, puis coder
fold_left_arbre
. On pourra utiliser intelligementList.fold_left
pour gérer le cas desNoeud
. Tester en calculant la somme des éléments d'arbres bien choisis.
On peut remarquer que reduce
du TP4 ressemble énormément à fold_left_arbre
: les deux vont parcourir les éléments de l'arbre les combinant via un accumulateur. Elles diffèrent cependant sur les points suivants:
-
reduce
prend en argument une fonction de type'a -> 'a -> 'a
alors quefold_left_arbre
prend une fonction un peu plus générique de type'b -> 'a -> 'b
. -
reduce
renvoie forcément uneoption
alors quefold_left_arbre
renvoie uniquement une option si'b
est lui-même uneoption
.
En utilisant intelligement
fold_left_arbre
, recoderreduce
.
Recoder
list_of_arbre
en utilisantfold_left_arbre
.