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

Caml Discussion :

Expressions fonctionnelles - inférences


Sujet :

Caml

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    2
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2009
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Expressions fonctionnelles - inférences
    Bonjour à tous!
    Je suis étudiante en Licence informatique. Malheureusement, je dois aller au rattrapage en septembre. Mon problème principal est la programmation fonctionnelle. Ce n'est pas du tout ma matière préférée mais il faut s'y coller!

    Alors, je suis au début de mes révisions et je bloque un peu sur ce genre d'exercices:
    Donner des expressions Caml qui correspondent aux types suivants:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int->int->int
    int->int->int->int
    int->(int->int)
    int->(int->int)->int
    int->(int->int->int)
    (int->int)->int->int
    Alors moi je bloque quand il y a des parenthèses, ou quand il y a trop de "int", je ne vois pas quelle forme va prendre la fonction.
    Si quelqu'un veut bien m'expliquer clairement les démarches pour répondre à cet exo ou si quelqu'un a un tuto ou un cours? J'ai regardé un peu dans les cours, mais je n'ai pas trouvé.

    Merci d'avance
    Déborah

  2. #2
    Membre éprouvé
    Avatar de InOCamlWeTrust
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 036
    Points : 1 284
    Points
    1 284
    Par défaut
    Pour comprendre ceci, tu dois d'abord comprendre la flèche.

    La flèche est uniquement associative à droite : a -> b -> c signifie a -> (b -> c).

    Décompose chaque expression et tu arriveras sans mal à trouver un exemple.

    Si on te demande, par exemple, int -> int -> int, c'est pour insister sur le fait que la fonction possède deux arguments. Un exemple serait...

    Si on avait voulu une fonction à un argument retournant une nouvelle fonction à un argument, on aurait écrit int -> (int -> int). Entre autres, on aurait pu proposer...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    let f n =
      if n > 0 then
        (+) 2
      else
        (+) 6

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Une bonne méthode pour résoudre ces exercices facilement est de commencer par les parties "sans parenthèses" : le type de fin, à droite de la dernière flèche, est le type de retour, les autres sont les types des paramètres.

    Par exemple si tu veux une fonction de la forme "a -> b -> c -> d", tu vas écrire "let f x y z = ...", en t'assurant que x est de type a, y de type b, z de type c, et que tu renvoies le type d.

    Concrètement, comment forcer les variables à être d'un type précis ? En utilisant des opérations de ce type dessus. Si tu écris par exemple "let f x = if x = 1 then x else x", tu as comparé x avec un entier, donc le type de x est forcément "int", et tu renvoies toujours x donc le type de retour est encore "int" (tu peux aussi utiliser des additions et renvoyer un entier, mais tu n'auras pas ces possibilités pour tous les types).

    La partie délicate concerne les parenthèses : elles désignent le type d'une fonction, qui est soit l'un des paramètres, soit la valeur de retour. Pour obtenir le type d'une fonction en valeur de retour, c'est facile, tu fais comme pour résoudre l'exercice globalement : si tu as int -> (int -> int -> int) par exemple, tu dois écrire
    Mais n doit être un entier, et tu dois renvoyer une fonction de type (int -> int -> int) donc avec deux paramètres et une valeur de retour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let f n =
      let g a b = if a = 0 && b = 0 then a else a
      if n = 0 then g else g
    Quand les types fonctionnels doivent apparaître parmis les paramètres, c'est un peu plus compliqué : au lieu de construire la fonction toi-même (comme g ici) tu dois l'"utiliser" puisqu'elle t'es passée en paramètre. Pour la forcer à avoir le bon type, tu dois lui donner le bon nombre de paramètres, du type demandé, et forcer sa valeur de retour à être du bon type. Pour "int -> (int -> int -> int) -> int" par exemple :
    Ici x sera "int" et g "int -> int -> int" (d'où le nom "g", héhé malin), et il faut trouver un bout de code qui force "g" à être une fonction comme il faut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let f x g =
       let retour_g = g 0 0 in
       if x = 0 && retour_g then 0 else 0
    En écrivant "g 0 0", j'ai forcé g à admettre (au moins) deux paramètres de type "int", et le test sur "retour_g" force la valeur de retour à être de type "int" aussi (bien sûr la déclaration locale n'est pas nécessaire, tu peux écrire "&& g 0 0 = 0").

    L'exercice devient plus intéressant, je trouve, avec des types polymoprhe. Tu as une idée de comment écrire une fonction de type 'a -> 'b -> ('c -> 'd) -> ('b -> 'a -> 'c) -> 'd ?

  4. #4
    alex_pi
    Invité(e)
    Par défaut
    Je me permets de pas être d'accord avec un point des deux réponses précédentes. Moi si je suis un examinateur et que je demande une fonction de type int -> int -> int et une de type int -> (int -> int) et que l'élève ne me répond pas "c'est la même chose, je vous donne donc la même fonction", je considère qu'il n'a pas bien compris le parenthesage de la flèche..

  5. #5
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Salut !

    Citation Envoyé par alex_pi
    Je me permets de pas être d'accord avec un point des deux réponses précédentes. Moi si je suis un examinateur et que je demande une fonction de type int -> int -> int et une de type int -> (int -> int) et que l'élève ne me répond pas "c'est la même chose, je vous donne donc la même fonction", je considère qu'il n'a pas bien compris le parenthesage de la flèche..
    À moins que le cours n'ait jamais évoqué la curryfication et que l'enseignement ait été effectué en distinguant de manière très arbitraire les arguments d'une fonction et le résultat renvoyé (je ne sais pas si ce que je dis est clair). Évidemment passer à côté de ça est une énormité : on ne comprend plus vraiment l'utilité de la flèche, ni la puissance de l'approche fonctionnelle.

    D'où : Déborah, dans ton cours, est-il fait mention de la notion de curryfication à un moment ou à un autre ?

    Cordialement,
    Cacophrène

  6. #6
    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
    Citation Envoyé par alex_pi Voir le message
    Je me permets de pas être d'accord avec un point des deux réponses précédentes. Moi si je suis un examinateur et que je demande une fonction de type int -> int -> int et une de type int -> (int -> int) et que l'élève ne me répond pas "c'est la même chose, je vous donne donc la même fonction", je considère qu'il n'a pas bien compris le parenthesage de la flèche..
    Je suis complètement d'accord, si cette remarque n'est pas faite je ne mettrais pas le maximum des points même si toutes les fonctions fournies sont du bon type.

    --
    Jedaï

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Non, moi je m'attends à des fonctions différentes justement (parce que les parenthèses permettent plus d'expressivité, c'est une manière de préciser au lecteur humain quelque chose), et d'ailleurs ça ne revient pas exactement au même parce que les fermetures seront placées diféremment (même si les types eux sont bien identiques).

    Dans tous les cas, je trouve que c'est du détail, je comprends très bien que d'autres personnes aient un avis différent, par contre je trouverais abusif d'enlever des points à un examiné qui n'est pas du même avis.

  8. #8
    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
    Citation Envoyé par bluestorm Voir le message
    Dans tous les cas, je trouve que c'est du détail, je comprends très bien que d'autres personnes aient un avis différent, par contre je trouverais abusif d'enlever des points à un examiné qui n'est pas du même avis.
    Ce n'est pas une question d'avis, même s'il mettait des fonctions différentes je serais content, à partir du moment où il fait la remarque que les types 1 et 3 sont en réalité identiques. Il me semble bien que la question est aussi là pour tester la compréhension du currying par l'examiné. (Dans le doute, et vu que la question ne comprend pas le "Avez-vous une remarque sur ces types ?" que je rajouterais si j'avais à la rédiger, je mettrais plutôt un bonus à ceux qui feront la remarque).
    --
    Jedaï

  9. #9
    Nouveau Candidat au Club
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2009
    Messages
    2
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2009
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Tout d'abord merci à tous pour vos réponses.

    Je suis d'accord avec alex pi parce que mon prof m'a précisé que les parenthèses (quand elles sont situées à la fin) peuvent être omises.

    Quant à la curryfication, mon prof de TD n'a pas vraiment assuré et nous n'avons fait que 2 exos sur le TD concerné. Vous voyez que j'ai du mal avec les "int", alors vous imaginez bien que quand on me demande d'écrire une fonction qui renvoie l'inférence 'a->'b->'c ou quelque chose comme ça, je suis un peu larguée!

    En tout cas merci pour vos réponses, je vais encore me pencher là-dessus et si j'ai encore un souci, je vous redemanderai. De toutes façons, je pense qu'on se reverra dans le forum Java, vu que je suis perdue dans ce langage à cause des grèves de nos chers profs.

    Déborah

  10. #10
    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
    Citation Envoyé par ladeb Voir le message
    Vous voyez que j'ai du mal avec les "int", alors vous imaginez bien que quand on me demande d'écrire une fonction qui renvoie l'inférence 'a->'b->'c ou quelque chose comme ça, je suis un peu larguée!
    Ca tombe bien que tu ais du mal à écrire cette fonction parce qu'en théorie tu ne peux pas... En effet ce type n'a pas d'habitant, tu ne peux pas prendre deux valeurs de deux types quelconques et renvoyer une valeur d'un type quelconque sans rapport avec les deux premiers. (En pratique tu peux utiliser "fail_with" pour obtenir ce type mais c'est acceptable vu que cette fonction ne terminera jamais vraiment (puisqu'elle s'achèvera en exception))

    De même, on ne peut écrire 'a -> 'b, on peut écrire 'a -> 'a et la seule fonction (qui termine sans exception) de ce type est l'identité, de même la seule fonction de type 'a -> 'b -> 'a est (fun x y -> x), il n'y en a pas d'autres (fonctions pures) !

    --
    Jedaï

  11. #11
    alex_pi
    Invité(e)
    Par défaut
    ATTENTION, ce qui va suivre peut embrouiller les débutants :

    Je rappelle que quasiment personne ne code dans des langages normalisant (où toutes les fonctions terminent), et que donc, malheureusement, on peut se passer d'exception pour retourner quelque chose de n'importe quel type...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    # let rec any_type () = any_type ();;
    val any_type : unit -> 'a = <fun>
    C'est bien ce qui fait qu'on peut difficilement les utiliser comme langage de preuve

  12. #12
    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
    Citation Envoyé par alex_pi Voir le message
    ATTENTION, ce qui va suivre peut embrouiller les débutants :

    Je rappelle que quasiment personne ne code dans des langages normalisant (où toutes les fonctions terminent), et que donc, malheureusement, on peut se passer d'exception pour retourner quelque chose de n'importe quel type..
    C'est vrai, c'est pour ça qu'en Haskell on a besoin d'introduire bottom dans la sémantique... Et de ce point de vue il y a toujours au moins un habitant à n'importe quel type : bottom, c'est à dire une valeur qui ne termine pas (ou qui "termine" avec une exception). Néanmoins on va dire qu'en général les types où bottom est le seul habitant ne sont pas très intéressants.

    --
    Jedaï

  13. #13
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    D'ailleurs quand on voit le traitement de bottom en Haskell, on se dit que les langages stricts dans le fond c'est pas mal, parce que les questions de lifting des types algébriques c'est quand même très laid.

  14. #14
    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
    Citation Envoyé par bluestorm Voir le message
    parce que les questions de lifting des types algébriques c'est quand même très laid.
    A quoi fais-tu allusion exactement, je ne suis pas parfaitement sûr de ce que tu désignes par ces termes ?

    --
    Jedaï

  15. #15
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Au fait que, par exemple, le nombre de représentants de (Either a b) n'est pas la somme des nombres de représentants de a et de b, ou que les types (t) et ((), t) et (t) ne sont pas isomorphes. C'est aussi pour ça qu'il y a "newtype" qui pourtant ne sert apparamment à rien, et que (let a = b in c) et (case b of a -> c) ne sont pas équivalents.

  16. #16
    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
    Citation Envoyé par bluestorm Voir le message
    Au fait que, par exemple, le nombre de représentants de (Either a b) n'est pas la somme des nombres de représentants de a et de b, ou que les types (t) et ((), t) et (t) ne sont pas isomorphes. C'est aussi pour ça qu'il y a "newtype" qui pourtant ne sert apparamment à rien, et que (let a = b in c) et (case b of a -> c) ne sont pas équivalents.
    Je vois ce que tu veux dire, c'est effectivement laid, mais pas trop dérangeant en général
    Par contre je conçois que ce soit difficile à comprendre pour un débutant, les différences sont subtiles et peuvent avoir des conséquences relativement importantes.

    --
    Jedaï

Discussions similaires

  1. Réponses: 20
    Dernier message: 20/01/2014, 00h38
  2. expression régulière décimale non fonctionnelle
    Par drumtof dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 10/09/2009, 11h01
  3. [Concept] Dépendances fonctionnelles
    Par bolo dans le forum Décisions SGBD
    Réponses: 4
    Dernier message: 24/01/2003, 20h13
  4. Expressions réguliéres
    Par Tooms dans le forum Langage
    Réponses: 4
    Dernier message: 06/12/2002, 18h42
  5. Réponses: 5
    Dernier message: 11/06/2002, 15h21

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