TP5 - Lipn

publicité
Principes de Programmation
TP5
22 mars 2017
On rappelle qu’il y a deux syntaxes possibles pour utiliser les monades :
– La première est plus “fonctionnelle”. Elle consiste à travailler comme s’il
n’y avait pas de monade et de rajouter des bindings =<< et des return là
où il faut.
– La seconde est plus “impérative”, c’est la “do-construction”.
En fait, les deux sont très similaires. Au lieu d’utiliser une application f=<<arg
dans l’environnement de la monade (avec f::a->m b et arg:m a), la do-construction
va utiliser une variable intermédiaire à valeur dans la monade :
do
x <- arg
f x
ici, x::a est calculé sans considérer la monade. L’effet de la monade est appliqué
à l’utilisation de la flèche <-.
Exercice 1 (La monade IO). Écrivez le programme suivant : 1
import
import
main :: IO
main = do
putStrLn
t
<start <end
<putStrLn
Control.DeepSeq
System.CPUTime
()
"Pour quelle taille de liste voulez-vous faire un test ?"
getLine
getCPUTime
deepseq (map (+1) [1..(read t)]) getCPUTime
("finit en "++ show(end-start))
1. Selon vous, que fait-il ? (Dans un premier temps, ignorez l’instruction
deepseq).
2. L’instruction deepseq :: a -> IO b -> IO b calcule le résultat du premier argument, l’oublie puis calcule le second. Quel est l’intérêt ici ? On
notera que cet opérateur est à utiliser avec parcimonie.
1. Attention à l’indentation !
1
3. Utilisez ghci pour avoir les type de getLine,de getCPUTime et de putStrLn.
4. Essayez de comprendre ce qui se passe, puis faites quelques essais. À noter
que “main” à toujours le type IO (). Cela signifie qu’il ne rend aucun
résultat dans haskell, mais que tout ce qui est calculé est envoyé dans
l’environnement (par exemple affiché sur la sortie standard).
5. Réécrire le même programme en utilisant des bindings =<< et des return
Exercice 2 (Suite du TD).
Essayez de compiler les exemples vus en TD (n’oubliez pas de changer les noms
pour éviter les conflits).
Exercice 3 (La monade des listes).
1. Écrivez une fonction
fixerVal :: Eq a => (a->b) -> a -> b -> (a -> b)
qui prend trois arguments : une fonction (f::a->b), une abscisse x::a et
une ordonnée y:b et qui rend une fonction f’::a->b qui est la même que
f excepté pour x où elle vaut y.
2. En l’utilisant, écrivez une fonction :
toutesVal :: Eq a, Enum b, Bounded b => (a->b) -> a -> [a -> b]
qui prend une fonction (f::a->b), une abscisse x::a et rend la liste des
fonctions obtenues faisant varier cette abscisse sur toutes ses valeurs possibles. 2
3. En utilisant le binding (=<<) :: (a->[b]) -> [a] -> b, écrivez la fonction :
toutesValListe :: Eq a, Enum b, Bounded b => (a->b) -> [a] -> [a -> b]
qui énumère toutes les valeurs possibles en changeant les éléments de la
liste de a.
4. Écrivez la fonction
valVerite :: Pred -> [Int -> Bool]
qui liste toutes les valeurs de vérité que l’on peut appliquer à un prédicat.
5. Écrivez une version avec une do-construction.
2. Indice : utilisez un map :: (b− > a− > b)− > [b]− > [a− > b].
2
Téléchargement