Forum Programmation.autre Problème de types en Haskell

Posté par  . Licence CC By‑SA.
Étiquettes :
1
21
oct.
2015

Bonjour,
j'ai de nouveau un souci en Haskell. Je code un générateur de GCode.

J'ai un type 'Operation a' qui me sert à créer des opérations (par exemple une poche circulaire, un contour, un carré, etc.), et à les composer entre elles.

si je fais runOperation (circularPocket 10 10 0.5) :: GCode, ça me retourne du GCode.
si je fais runOperation (circularPocket 10 10 0.5) :: Drawing, ça me retourne l'image du parcours de l'outil.
si je fais runOperation (circularPocket 10 10 0.5) :: BoundingBox, ça me retourne les limites du parcours de l'outil, sur chaque axe (x, y et z).

Je voudrais maintenant créer un opérateur qui prend en argument 2 opérations, qui calcule leur 'BoundingBox' et qui en fonction de ça les translate pour qu'elles soient juxtaposées.

je créée mon opérateur :

(|>|) :: Backend a => Operation a -> Operation a -> Operation a
op1 |>| op2 = do
    boundingbox1 <- op1
    boundingbox2 <- op2
    jefaismoncalculetjetranslate op1 op2

seulement voilà, le système de types détecte que op1 et op2 sont de type 'Operation BoundingBox' et non pas un type plus général 'Operation a'. Ce qui est normal mais du coup mon opérateur ne peut pas retourner de GCode. Je ne vois pas trop comment faire pour m'en sortir.

  • # Changer la signature peut-être ?

    Posté par  . Évalué à 4.

    Peut-être en écrivant une signature différente, où c'est pas le même a pour la dernière opération (peut-être qu'il faut des quantifieurs du coup, je sais pas). Ou alors, enlever la signature, et voir ce que décide Haskell (peut-être qu'il faut -XNoMonomorphismRestriction [plus sûr du nom] pour qu'il fasse un truc général et pas le contraire). Faut dire que haskell c'est plus trop frais dans ma mémoire :)

    C'est d'ailleurs ce petit genre de difficultés à répétition qui m'ont un peu agacé avec ce langage (plus le jour où je crois que je commence à comprendre comment ça marche, et puis je tombe sur des modules qui utilisent les Lens ou les Arrows et sont documentés à l'aide quasiment des seules signatures des fonctions, et là je reviens à mon Perl ;) ).

    • [^] # Re: Changer la signature peut-être ?

      Posté par  . Évalué à 1.

      quand j'enlève la signature, ça compile bien mais le type est restreint à 'Operation BoundingBox -> Operation BoundingBox -> Operation BoundingBox'.
      je viens d'essayer avec NoMonomorphismRestriction, et c'est pareil :(
      j'ai essayé de changer le dernier type, pour voir, mais ça ne compile pas.

      je vais regarder du côté des quantificateurs, je n'en ai jamais utilisé.

    • [^] # Re: Changer la signature peut-être ?

      Posté par  . Évalué à 1.

      ayé !
      j'ai regardé du côté des quantificateurs et je suis tombé sur ces 2 pages :
      Stackoverflow
      Explaining Haskell RankNTypes for All

      Du coup j'ai ajouté RankNTypes, j'ai modifié le type de ma fonction et ça marche !!

      {-# LANGUAGE RankNTypes #-}
      (|>|) :: Backend a => (forall a . Backend a => Operation a) -> (forall a . Backend a => Operation a) -> Operation a
      op1 |>| op2 = do
          BoundingBox [bx1, _, _] <- op1
          BoundingBox [bx2, _, _] <- op2
          jefaismoncalculetjetranslate op1 op2

      merci pour la piste des quantificateurs.

      • [^] # Re: Changer la signature peut-être ?

        Posté par  . Évalué à 3.

        Cool ! Et puis ça me fait réviser un peu aussi. Après, c'est pas forcément très apétissant ce genre de signatures :)

        • [^] # Re: Changer la signature peut-être ?

          Posté par  . Évalué à 1.

          ouais c'est clair. et puis j'avoue que j'ai bien galéré à le trouver. j'ai tatonné pas mal avant que ça compile.
          dans les articles que j'ai vu c'était marqué que pour bien comprendre les types avec forall, il fallait lire un bouquin sur la théorie des types !!! ça doit sûrement être intéressant, mais bon… dans une autre vie peut-être.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.