PROGRAMMATION FONCTIONNELLE : ELEMENTS DE CORRECTION
Exercice 1 : Questions de cours (6.5pts)
1- Considérons le programme C suivant : int i = 0 ; int g(int j) { i += j; return i; }
a- Que désigne-t-on par transparence référentielle d’un programme ? 1pt
La transparence référentielle d’un programme est une propriété dudit programme qui fait qu'il peut être remplacé par sa valeur de retour sans changer le comportement du contexte d’appel. b- Montrer que le programme précédent ne possède pas cette propriété. 1pt Avec le programme précédent, un premier appel de g avec pour argument 1 donne g(1) = 1, un second appel identique donne plutôt g(1) = 2. Par conséquent g(1) ne peut pas être remplacé par 1 ; pire encore g(1) – g(1) n’est pas nul. c- Quel en est la raison ? A partir de cet exemple, peut on dire que le programme précédent est un programme à effets de bord ? 0.5pt + 0.5pt La raison c’est que le programme manipule des variables globales. Oui, le programme précédent est un programme à effets de bords, car la fonction g utilise et modifie des variables non locales. d- Pourquoi dit-on que Haskell est un langage fonctionnel pur ? 1pt Parce qu’en Haskell, toutes les fonctions sont pures ; i.e. elles ne sont pas à effet de bords. 2- Que désigne-t-on par instanciation partielle des fonctions ? 1pt Instancier partiellement une fonction, c’est l’utiliser en fournissant juste une partie des arguments qu’elle attend. 3- Soit la fonction définie par square x = x * x. Proposer une réduction totale de l’expression e = (square (3 + 4)) + (5 - 2) en utilisant uniquement des réductions extérieures 1.5pts e = (square (3 + 4)) + (5 - 2) = ((3 + 4) * (3 + 4)) + (5 - 2) = (7 * (3 + 4)) + (5 - 2) = (7 * 7) + (5 - 2) = 49 + (5 - 2) = 49 + 3 = 52
Exercice 2 : Types et classes de types (8.5pts)
On voudrait écrire un module Haskell pour la manipulation des figures géométriques suivantes : les carrés, les rectangles et les cercles. Un cercle est défini par son centre qui est de type Point et son rayon de type Float. 1- Proposer les types Carre, Rectangle et Cercle correspondants. 1.5pts data Carre = MKCarre Float data Rectangle = MKRect Float Float data Point = MKPoint Float Float data Cercle = MKCercle Point Float
NB : accepter les types polymorphes
2- Donner les types des constructeurs de données de vos différents types. 1.5pts MKCarre :: Float -> Carre MKRect :: Float -> Float -> Rectangle MKPoint :: Float -> Float -> Point MKCercle :: Point -> Float -> Cercle
3- Proposer une classe de type FigureGeometrique contenant les signatures des
fonctions surface et perimetre qui permettent d’évaluer la surface et le périmètre des figures géométriques. 1.5pts class FigureGeometrique a where perimetre :: a -> Float surface:: a -> Float 4- Créer les instances de FigureGeometrique pour les types Carre, Rectangle et Cercle. 3pts instance FigureGeometrique (Carre) where perimetre (MKCarre cote) = cote * 4 surface (MKCarre cote) = cote * cote
instance FigureGeometrique (Rectangle) where
perimetre (MKRect long larg) = (long + larg) * 2 surface (MKRect long larg) = long * larg
instance FigureGeometrique (Cercle) where
perimetre (MKCercle (MKPoint x y) rayon) = pi * rayon * 2 surface (MKCercle (MKPoint x y) rayon) = pi * rayon * rayon 5- Ecrire une fonction evaluerSurfaces qui prend une liste de FigureGeometrique en paramètre et renvoie la liste de leurs surfaces respectives. 1pt
evaluerSurfaces :: FigureGeometrique a => [a] -> [Float]
Exercice 3 : Manipulation des types polymorphes (5pts)
On désire manipuler des nombres complexes en Haskell 1- Proposer un type polymorphe NombreComplexe a de donnée à cet effet 1pt data NombreComplexe a = MKComp a a 2- Représenter le nombre complexe -5i + 12.2 à l’aide de votre type. 1pt z1 = MKComp 12.2 -5 3- Que faut-il faire pour pouvoir comparer deux nombres complexes grâce aux opérateurs == et /= ? 1pt Il faudrait créer une instance de la classe Eq pour le type NombreComplexe 4- Ecrire une fonction somme qui fait la somme de deux nombres complexes.2pts somme :: Num a => NombreComplexe a -> NombreComplexe a -> NombreComplexe a somme (MKComp x y) (MKComp a b) = (MKComp (x + a) (y + b))