TD 3
Sommaire de documents
Cet exercice propose de manipuler et d’afficher une représentation de sommaire qui structure les différentes parties d’un document. Cette représentation est implémentée par les types suivants :
type
ou data
?
Il y a plusieurs différences entre data
et type
en Haskell.
-
data
définit un nouveau type distinct, avec ses propres constructeurs. Ces types supportent du filtrage de motif et peuvent définir des types plus complexes. -
type
définit un synonyme de type, un alias pour un type existant. Il n’y a pas de constructeur et cela permet essentiellement de rendre du code existant plus clair.
On utilise data
quand :
- on doit définir un type avec ses propres constructeurs ;
- on a besoin d’utiliser du filtrage de motif ;
- on veut un type qui peut représenter plusieurs possibilités (
Either
,Maybe
…).
On utilise type
quand :
- on veut simplifier des déclarations de type ;
- on veut donner des noms concrets à des types existants.
Le type Section t som
représente une section avec un titre t
et le
sommaire de ses sous-parties som
. Le type Sommaire
est donc
simplement une liste de Section
.
Étant donné un sommaire de la forme :
On veut pouvoir afficher une chaîne de caractères qui affiche le sommaire de façon numérotée comme ceci :
1. Transformer sections et sommaires en chaînes de caractères
On implémente deux fonctions (mutuellement récursives) :
-
sommaireToStrings :: Sommaire -> [String]
, qui transforme un sommaire en la liste des lignes utilisées pour son affichage ; -
sectionToStrings :: Section -> [String]
qui transforme une section en la liste des lignes utilisées pour son affichage.
Le principe, c’est que sommaireToStrings
va appliquer
sectionToStrings
à chaque élément de son sommaire, et concaténer les
résultats (sinon, on se retrouve avec des listes de listes de listes).
2. Numérotation des sections et sommaires
Tout ceci, c’est très bien, mais on n’a pas de numérotation des éléments.
On va donc procéder de la même manière que précédemment, mais en ajoutant la numérotation. On aura deux fonctions :
-
numSommaire :: String -> Sommaire -> Sommaire
, qui va renvoyer un nouveau sommaire dont tous les titres de sections sont modifiés pour faire figurer devant une chaîne de caractères et le numéro ; -
numSection :: String -> Int -> Section -> Section
, qui va renvoyer une nouvelle section avec un titre obtenu en ajoutant une chaîne et un numéro, et un sommaire précédé de".."
pour les décaler dans l’affichage.
Quand on est face à un sommaire, on utilise la liste [1..]
en prime
pour avoir la numérotation et on zippe avec la fonction numSection
,
qui va numéroter chaque section.
La numérotation d’une section est le numéro devant le titre et ensuite
on rappelle la numérotation sur le sommaire de la section, avec une
chaîne de départ décalée et pré-numérotée.
Si on reprend notre exemple de tout à l’heure, on a :
3. Afficher le sommaire
On va écrire une fonction showSommaire :: Sommaire -> String
qui
numérote un sommaire puis le transforme en chaîne de caractères.
On va utiliser la fonction unlines :: [String] -> String
qui
concatène une liste de chaînes avec des sauts de lignes.
Si on affiche le résultat sur notre exemple, on a bien :