Licence STS, semestre 4 2009–2010
Langages et Génie Logiciel (Info 223)TP 6
  
Modules et foncteurs

L’objectif de ce TP est de vous familiariser avec la manipulation de modules et foncteurs. Ce TP s’appuie sur les primitives du projet, mais l’utilisation de foncteurs n’est pas forcément la meilleure solution dans ce cas particulier, aussi il n’est pas demander d’intégrer ce code directement dans votre projet (cf question 6 pour des suggestions en rapport avec le projet).

On utilisera une bibliothèque de vecteurs, on suppose qu’elle se trouve dans un fichier vector.ml et qu’elle définit le type t.

Un exemple de telle bibliothèque: Si vous le souhaitez, vous pouvez utiliser la bibliothèque suivante: Interface de la bibliothèque de vecteurs Code compilé de la bibliothèque de vecteurs.

  1. Définir une signature OBJECT pour représenter les objets tels que les vaisseaux adverses ou les missiles. Cette interface définira un type t pour les objets ainsi que les fonctions suivantes: On rappelle que la syntaxe pour une interface de module est:
    module type OBJECT = sig
      type t
      val create : ...
      ...
    end
    
  2. Implanter un module Adv1 qui implante cette signature dans lequel l’objet est un ennemi bleu, la vitesse initiale de l’objet est le vecteur (0,5) et cette vitesse ne change pas lors des déplacements. On rappelle que la syntaxe pour une interface de module est:
    module Adv1 = struct
      type t = ...
      let create = ...
      ...
    end
    
  3. Définir ensuite un foncteur ObjectSet qui prend en argument un module M de signature OBJECT et qui implante un module qui définit un type t pour représenter des ensembles d’objets ainsi que les fonctions suivantes: Pour implanter ce foncteur on utilisera le foncteur Set.Make pour représenter des ensembles dont on rappelle les principales composantes:
    module Set  :
      sig
        module type OrderedType = sig type t val compare : t -> t -> int end
        module Make :
          functor (Ord : OrderedType) ->
            sig
              type elt = Ord.t
              type t
              val empty : t
              val is_empty : t -> bool
              val mem : elt -> t -> bool
              val singleton : elt -> t
              val add : elt -> t -> t
              val union : t -> t -> t
              val compare : t -> t -> int
              val equal : t -> t -> bool
              val iter : (elt -> unit) -> t -> unit
              val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
              val filter : (elt -> bool) -> t -> t
              val cardinal : t -> int
              val elements : t -> elt list
              ...
            end
      end
    
    La syntaxe pour définir un foncteur est:
    module ObjectSet (M:OBJECT) = struct 
        module Ord = ...
        module ObjSet = ...
        type t = ...
        let create = ...
    ...
    end
    
  4. Instancier le foncteur ObjectSet sur le module Adv1, écrire une fonction new_adv qui étant donné un entier n crée une vague de n vaisseaux répartis sur le haut de l’écran. Tester les fonctions.
  5. Optionel On suppose donnée une référence globale ship correspondant au joueur principal et deux fonctions ship_pos et ship_speed de type unit Vector.t donnant sa position et sa vitesse.
  6. On pourrait penser introduire un nouveau module pour représenter un autre type d’adversaire (les enemmis rouges). Cependant cette approche n’est pas recommandée car l’état du système devrait alors contenir un ensemble de vaisseaux bleus, un ensemble de vaisseaux rouges… ce qui empèche de factoriser le code. Pour représenter différentes catégories d’adversaires, il est préférable d’utiliser un unique type de données avec un champs supplémentaire permettant de distinguer les comportements.

    Pour cela on peut ajouter à la signature OBJECT un type abstrait info qui permet de caractériser l’adversaire (couleur, vitesse initiale, frottement …) et la fonction create prendra alors en argument une position et un objet de type info.


Ce document a été traduit de LATEX par HEVEA