Programmation Fonctionnelle Avancée – Master 1 TP 11

publicité
Programmation Fonctionnelle Avancée – Master 1
TP 11
Mehdi Dogguy
Pour utiliser du code C depuis votre code Haskell, il faut utiliser la FFI
(the Foreign Function Interface). Pour ce faire, il suffit de rajouter, au début
de votre code Haskell l’en-tête suivant :
{-# LANGUAGE ForeignFunctionInterface #-}
Ensuite, pour pouvoir utiliser les types C, il suffit d’importer (suivant les
besoins) quelques modules :
import Foreign.C.Types -- Définitions de types
import Foreign.C.String -- Fonctions sur CChar et CString
import Foreign.Ptr
-- Pointeurs (définition et opérations usuelles)
Enfin, vous pouvez commencer à importer les fonctions C qui vous
intéressent dans le monde Haskell. Cette opération est réalisée par le bout de
code suivant :
foreign import ccall "fonction_c" fonction :: Signature
où :
– ccall représente la convention d’appel utilisée. ccall représente celle utilisée par C, mais il en existe d’autres comme : cplusplus, dotnet, jvm,
etc. . . Durant ce TP, on va se limiter à ccall seulement.
– fonction c le nom de la fonction C à importer, potentiellement précédé
par le nom du module qui la définit (Exemple : math.h définit, entre
autres, les fonctions cos et sin) et séparés par un espace.
– fonction le nom de la fonction Haskell, dont la signature est Signature,
que vous allez utiliser dans votre code Haskell. Notez que la Signature
devra utiliser les types définis dans Foreign.C.Types.
En C, une fonction qui retourne void peut avoir des effets de bord pendant
son exécution. En Haskell, ces fonctions impures doivent retourner IO (). De
façon plus générale, les fonctions C impures qui retournent un type t doivent
être importées en tant que fonctions retournant un type IO t’, où le type t’
correspond à la version Haskell du type C t.
La suite du TP se déroulera en deux parties. Dans un premier temps, nous
allons voir comment interfacer Haskell avec C pour des fonctions simples. Ensuite, nous allons essayer de coder un vrai programme qui utilise la bibiliothèque
zlib.
Exercice 1 :
FFI
– Implémentez la fonction convert double :: CDouble -> Double, qui
convertit un CDouble en Double.
– Fonction pure :
1. Définissez la fonction c sin, à partir de la fonction C sin qui se
trouve dans le module math.h.
2. Définissez la fonction h sin :: Double -> Double qui calcule le sinus de l’argument, en utilisant la fonction c sin.
– Fontion impure :
3. Définissez la fonction c time à partir de la fonction C time.
Écrivez un programme qui affiche le temps écoulé, en secondes, depuis le 1er
Janvier 1970 1 et h sin(x) pour chaque argument x passé comme argument en
ligne de commande.
Exercice 2 :
Commande zpipe
Pour cet exercice, il vous faudra récupérer le fichier zbits.c (qui contient des
fonctions C définies autour des fonctions inflate et deflate de la bibliothèque
zlib) depuis la page web des TPs. Le fichier zpipe.c est fournit seulement à
titre d’exemple, mais n’est pas nécessaire pour cet exercice.
1. Créer un Makefile qui comporte 3 cibles :
zbits.o qui produit un fichier du nom de la cible à partir du fichier
zbits.c
hzpipe qui compile votre programme Haskell Hzpipe.hs en un binaire.
all qui produit un programme nommé hzpipe à partir des cibles
précédemment définies.
clean qui supprime les fichiers générés.
(?) Il faudra passer -lz à ghc pour linker l’exécutable final.
2. Créez Hzpipe.hs et importez les fonctions définies dans zbits.c, i.e. inf
(la fonction de compression) et def (la fonction de décompression).
3. Faites en sorte que votre programme hzpipe compresse et décompresse
des fichiers en utilisant les fonctions précédemment importées. (À vous de
choisir comment votre programme doit être appellé).
– Comment le type FILE de C est représenté en Haskell ?
4. Les fonctions retournent un entier qui est censé correspondre à un
cas d’erreur. Affichez un message clair en cas d’erreur (les informations à propos codes d’erreur peuvent être trouvées dans zpipe.c et
/usr/include/zlib.h).
1. Cette information est le résultat de c time
Téléchargement