IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Haskell Discussion :

De l'intérêt des Monads Transformers


Sujet :

Haskell

  1. #1
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut De l'intérêt des Monads Transformers
    Je voulais savoir, est-il fréquent et surtout utile de déclarer une instance de la classe MonadTrans à chaque fois que l'on crée une Monade ?

    Par exemple, je réfléchis à comment réaliser un jeu de snake, j'ai un type Canvas déclaré ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    newtype Canvas i s a = Canvas (State (Array i s) a)
       deriving (Monad)
    Je fournis ensuite des opérations pour manipuler un canevas (ajouter un élément, bouger les éléments mobiles (le snake, par exemple), etc.). Ce sont des fonctions monadiques, donc leurs valeurs de retour seront toujours de type Mes questions sont:
    1) Pensez-vous qu'il soit au final utile que Canvas soit une Monade ? Je pourrais aussi bien le déclarer ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    newtype Canvas i s = Canvas (Array i s)
    Et les fonctions pour manipuler un canevas prendraient simplement un argument de type "Canvas i s".
    Pensez vous qu'utiliser le canevas comme une Monade représente un avantage réel ou bien n'est-ce plutôt ici qu'un "style de codage" pour éviter d'avoir à passer explicitement mon canevas en paramètre à chaque fonction qui le manipule ?

    2) Si Canvas est bien une monade, est-il utile de déclarer une classe MonadCanvas (qu'instancierait le type Canvas) définissant les méthodes de manipulation d'un canevas, et de créer un type CanvasT qui instancierait à la fois MonadCanvas et MonadTrans ? (pour suivre le modèle des monades Reader, Writer, State, etc.)
    En d'autres termes, est-il souhaitable à chaque fois que l'on crée une monade de créer le monad transformer associé ?

    Je pose ces questions car si j'ai bien pigé l'utilité des monades de base de Haskell, je n'ai pas encore tout a fait saisi quand je peux ou non tirer profit des monades dans mes types à moi.

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 36
    Points : 54
    Points
    54
    Par défaut
    Dans ce cas précis, l'utilisation d'une alias de type n'aurait-elle pas été plus simple? Car packer/dépacker Canvas juste pour ça ne semble pas forcément utile, en plus t'aurais déjà du MonadTrans sans avoir à écrire une ligne du coup.

  3. #3
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    En fait, j'utilise le newtype pour cacher l'intérieur du Canvas. L'utilisateur du Canvas ne sait pas qu'il manipule un State.
    Et je cherche pas à savoir comment avoir un MonadTrans le plus simplement possible, je cherche à savoir si ça peut être utile.
    Voir mes deux questions dans mon premier post.

  4. #4
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    En fait, je réalise que j'ai mal posé ma question.
    Mon problème de décision se pose dans des cas plus simples :
    Mettons qu'on veuille coder un jeu de Morpion (cas assez simple et typique de programmation), on va forcément avoir quelque part un datatype du type GrilleDeJeu. Comment réaliseriez vous ce type, en vue de l'utilisation qu'on va en faire après ?
    Est-ce un simple conteneur que l'on utilise via des fonctions du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fonction :: GrilleDeJeu -> qqch -> (GrilleDeJeu, qqch)
    ?
    Lui donne-t-on une apparence de Monade, soit en le déclarant soi-même instance de Monad soi en basant sur State ou ST ?
    Ou encore autre chose ?

    En clair, comment représenteriez-vous en Haskell votre jeu de Morpion ?

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Il me semble qu'un simple type "GameState" (enregistrement ou simple conteneur si cela suffit) avec des fonctions pour le manipuler serait le plus simple, à intégrer ensuite dans une monade State (avec éventuellement un synonyme de type) si besoin est.

    --
    Jedaï

  6. #6
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    C'est ça que j'aurais fait, je pense, à la différence que mes méthodes de manipulation manipuleraient directement le State.
    En gros :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    data GameGrid = ... -- Un simple conteneur
    type GameMonad a = State GameGrid a
     
    function :: a -> GameMonad b
    (J'évite d'utiliser le terme "state" dans mes types, il porte à confusion, on ne sait pas si je me réfère à mon alias de State (ma GameMonad) ou bien l'état contenu dans le State (ma GameGrid)).

    Et sinon, Jedai (et là je rejoins ma question initiale), tu penses que déclarer mon GameMonad non pas comme un alias de State mais de StateT pourrait être utile ? Je risque d'avoir besoin d'embedder des action IO, par exemple.
    Du coup, mon type de base ne serait plus seulement une simple monade mais un transformeur de monade. Genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type GameMonadT m a = StateT GameGrid m a
    (on a GameMonad == GameMonadT Identity)

    J'imagine que mon problème de conception est assez commun en Haskell pour un habitué de la POO, non ?

  7. #7
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    A ta place, je commencerais par écrire toutes les fonctions de manipulation de façon non-monadiques... Il est aisé de les convertir en actions monadiques par la suite et avoir une version pure peut-être utile (avoir un module avec la version monadique et un avec les primitives pures est envisageable pour éviter les conflits de noms).

    Par ailleurs, il est préférable de ne pas lier directement tes fonctions à une monade ou à un transformateur de monade, mais juste à la classe MonadState :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    movePawn :: (MonadState GameGrid m) => Piece -> m Boolean
    movePawn p = do
      (gg, took) <- gets (Pure.movePawn p)
      put gg
      return took
    Ainsi, tu peux utiliser "State GameGrid" ou "StateT GameGrid m" ou même "MaybeT (State GameGrid)" par la suite sans changer la fonction.

    --
    Jedaï

  8. #8
    Membre du Club Avatar de limestrael
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 86
    Points : 57
    Points
    57
    Par défaut
    L'idée des 2 modules, l'un pur, l'un monadique, avec les mêmes noms de fonctions est bien.
    Effectivement, se baser sur la classe MonadState plutot que sur State ou StateT permet aussi d'être plus générique.

    Par contre, plutôt que de parler tout le temps de "MonadState GameGrid m", j'ai préféré déclarer une nouvelle classe ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class (MonadState GameGrid m) => MonadGame m
    (ça nécessite l'extension de GHC FlexibleContexts, par contre...)
    C'est juste un "alias de classe", en gros.

    MaybeT ? Ça n'existe pas en standard, ça, non ?
    Au fait, quelle est la diférence entre < MaybeT (State GameGrid) a > et < StateT GameGrid Maybe a > ??

Discussions similaires

  1. Performances : intérêt des vues ?
    Par Mr N. dans le forum Requêtes
    Réponses: 4
    Dernier message: 20/10/2005, 13h42
  2. Intérêt des TActionList
    Par Invité dans le forum C++Builder
    Réponses: 4
    Dernier message: 11/03/2005, 17h31
  3. [glut] de l'intérêt des listes
    Par khayyam90 dans le forum OpenGL
    Réponses: 3
    Dernier message: 26/07/2004, 10h35
  4. Quel est l'intérêt des Services Web ??
    Par silvermoon dans le forum Débats sur le développement - Le Best Of
    Réponses: 19
    Dernier message: 12/02/2003, 22h28
  5. [Technique] Intérêt des index
    Par ddams dans le forum Décisions SGBD
    Réponses: 10
    Dernier message: 04/11/2002, 15h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo