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 :

Même commande - resultats differents entre run main et console en direct


Sujet :

Haskell

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 113
    Points : 64
    Points
    64
    Par défaut Même commande - resultats differents entre run main et console en direct
    Bonjour,
    Encore une question du débutant en Haskell.
    Voici un petit code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    y =  0.0:[]
    x =  4.0:[]
    a = -0.4:[]
    b =  0.0:[]
    f =  ((head a)*(head x) + (1-(head a))*2*(head x)^2 / (1+(head x)^2)):[]
    c = "OK"
    x' =0.0:[]
    y' =0.0:[]
    f' =0.0:[]
     
    main =
         do
    	let x' = ((head b)*(head y) + (head f)):[]
    	    f' =  ((head a)*(head x') + (1-(head a))*2*(head x')^2 / (1+(head x')^2)):[]
    	    y' = ((head f') - (head x)):[]
    	    x = (head x'):[]
        	    y = (head y'):[]
    	print c
    Le code et accepté par WIN GHCi, interpreté et run main imprime bien OK.
    Par contre le contenu des listes ne change pas, alors que si après run main j'utilise les mêmes lignes directement sur la console (précédée de let), ça marche parfaitement, les listes changent.
    Il doit y avoir une raison que je ne trouve pas.
    Pourriez vous m'aider, SVP.
    Salutations

  2. #2
    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
    Haskell ne fonctionne pas ainsi... Les valeurs des "variables" ne changent pas une fois affectée (ou plutôt "nommée" justement). Tout au plus peut-on supplanter une variable définie dans une certaine portée par une variable du même nom dans une portée plus limitée, par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    let x = 5
    in {
      let x = 3
      in {
        print x
      }
    }
    la sortie sera "3" parce que le deuxième "x" supplante le premier dans la portée intérieure. Ce n'est bien sûr pas particulièrement recommandé...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    do
      let x = 5
      print x
      let x = 3
      print x
    Ce code imprime 5 puis 3 mais c'est parce que le bloc "do" n'est que du sucre syntaxique et le code réel est plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    let x = 5 in print x >> (let x = 3 in print x)
    Qui fonctionne pour la même raison que précédemment. Comme GHCi se comporte en gros comme un grand bloc do implicite, cela explique aussi pourquoi "ça marche" si tu entres ton code ligne à ligne dans GHCi.

    Maintenant pour bien voir qu'on ne peut pas modifier la valeur d'une "variable", tu peux faire :
    Ou simplement mettre deux définitions de x au top-level, GHC va se plaindre qu'il y a deux définitions de "x" en conflit.

    Si tu ne vois pas la différence, essaie ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    main = do
      let x = 5
      print x
      FonctionQuiChangeX
      print x
     
    FonctionQuiChangeX = do
      let x = 3
      print x
    La sortie sera 5 puis 3 puis 5 car la variable x dans la FonctionQuiChangeX() n'a rien à voir avec la variable dans main() (en fait comme x n'est déclarée que dans main(), la fonction ne peut pas y accéder puisqu'elle est déclarée au top-level).

    Par ailleurs je ne comprend pas ton code, pourquoi écrire :
    plutôt que :
    ou même :
    puisque tu ne sembles pas utiliser y à part avec "head y".

    Je ne comprend pas ce que tu cherches à faire ?
    Si tu veux répéter une tâche avec des valeurs différentes pour les paramètres, c'est là qu'on utilise une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    main = do
      tacheRepetee 2 3
     
    tacheRepetee 30 _ = return ()
    tacheRepetee a b = do
      print a * b
      tacheRepetee (a+1) (b+2)
    Comme tu le vois dans ce code, je ne modifie pas les valeurs de variables, j'appelle simplement tacheRepetee() avec des paramètres différents.

    --
    Jedaï

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 113
    Points : 64
    Points
    64
    Par défaut
    Bonjour,
    Merci pour votre réponse.
    Je ne cherche pas a modifier la valeur des variables mais a substituer les premières éléments des listes.
    Ça me permettra de calculer en boucle les coordonnées x y en condition des nouveaux éléments des listes.
    Avant d'écrire le code je vérifie toujours directement sur la console la validité.
    C'est la première fois que je tombe sur une chose qui marche sur la console et pas dans le code. Habituellement ça va de paire.

  4. #4
    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
    Je ne cherche pas a modifier la valeur des variables mais a substituer les premières éléments des listes.
    En d'autre terme tu veux modifier les valeurs des variables... Ces variables ne sont pas des pointeurs vers une structure de donnée que tu pourrais modifier, elles désignent la valeur que tu leur as assigné et ne peuvent changer.

    Ça me permettra de calculer en boucle les coordonnées x y en condition des nouveaux éléments des listes.
    Pas de boucles en programmation fonctionnelle : tout est fait soit directement par récursivité ou en utilisant des fonctions d'ordre supérieur comme map(), foldr(), foldl'(), iterate(), ...

    Exemple de boucle pour calculer le n-ième terme de la suite de Fibonacci (tout terme de la suite est le résultat de la somme des deux termes précédents, la suite commence par 1 et 1) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def fib(n):
      a, b = 1, 1
      i = 0
      while i < n :
        a, b = b, a+b
        i = i+1
      return a
    En Haskell on pourrait remplacer cette boucle par une fonction récursive :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    fib n = go n 1 1
      where 
        go 0 a b = a
        go i a b = go (i-1) b (a+b)
    Ou par une liste infinie dont on prend un index :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fib n = fst (fibs !! n)
      where fibs = iterate (\(a,b) -> (b, a+b)) (1,1)
    On peut même créer une liste qui se construit de façon récursive par rapport à elle-même :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fibs = 1:1: zipWith (+) fibs (tail fibs)
    C'est la première fois que je tombe sur une chose qui marche sur la console et pas dans le code. Habituellement ça va de paire.
    En fait non, ton code ne marche ni "dans le code" (écrit dans un script) ni dans la console, essaie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    :{ let main =
         do
    	let x' = ((head b)*(head y) + (head f)):[]
    	    f' =  ((head a)*(head x') + (1-(head a))*2*(head x')^2 / (1+(head x')^2)):[]
    	    y' = ((head f') - (head x)):[]
    	    x = (head x'):[]
        	    y = (head y'):[]
    	print c
    in main :}
    dans la console (:{ commence le mode multi-ligne) et tu verras que ça ne marche pas. C'est parce que tu rentres directement les lignes de ta fonction dans le bloc do implicite de ghci que tu as l'impression qu'elle "marche".

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 113
    Points : 64
    Points
    64
    Par défaut
    C'est donc l'explication : ligne par ligne ça marche, mais en multilignes non.
    Hélas por moi ça ne résout pas mon problème. Voici le code complet de ce qu je voudrais faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    import Graphics.Gloss
     
    y =  0.0:[]
    x =  4.0:[]b =  1.0:[]
    a = -0.4:[]
     
    f =  ((head a)*(head x) + (1-(head a))*2*(head x)^2 / (1+(head x)^2)):[]
    x'=  0.0:[]
    y'=  0.0:[]
     
    main =
         do
            let x'=((head b)*(head y) + (head f)):[]
    	    f =((head a)*(head x') + (1-(head a))*2*(head x')^2 / (1+(head x')^2)):[]
    	    y'=((head f) - (head x)):[]
                x =(head x'):[]
                y =(head y'):[]
            dessin
            main 
     
    picture = pictures   
    	[ (translate (10*(head x)) (10*(head y)) (point))
     	]
     
    myColor n = ( [ca,cb,cc,cd,ce,cf,cg,ch,ci,cj,ck,cl,cm,cn,co,cp] !! abs(round(n)) )
    ca = white
    cb = light(light yellow)
    cc = light yellow
    cd = yellow   
    ce = light(light orange)
    cf = light orange
    cg = orange
    ch = light (dark orange)
    ci = light red
    cj = red
    ck = dark red 
    cl = light violet
    cm = violet
    cn = light(light (dark violet))
    co = light ( light blue)
    cp = light blue
     
    point = color (myColor (3*(head f))) (circle 0.5)
     
    dessin =	
          display  
    	 (InWindow
    	       "Selle" 	 -- window title
    		(300, 300) 	 -- window size
    		(10, 10)) 	 -- window position
    	black                   -- background color
            picture                  -- picture to display
    Ca marche, mais les coordonnée x et y ne changeant pas et le point est affiché toujours au même endroit.
    En utilisant map et autres je n'arrive pas à créer une itération de main qui calcule les nouvelles valeurs de x et y en fonction de leurs valeurs précédentes, ainsi que le "f" qui détermine le nouveau point.

    Bon, je continue de chercher.

  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
    C'est donc l'explication : ligne par ligne ça marche, mais en multilignes non.
    ... Non le mode multiligne ne change rien à l'exécution du code, ce qui change c'est que les déclarations sont dans une fonction (et n'affecte donc rien hors de cette fonction) et non directement dans le bloc do implicite de ghci. Tu peux tester pour t'en convaincre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    :{ let 
      x' = ((head b)*(head y) + (head f)):[]
      f' =  ((head a)*(head x') + (1-(head a))*2*(head x')^2 / (1+(head x')^2)):[]
      y' = ((head f') - (head x)):[]
    :}
    Bon, venons-en à ton code. Primo, débarrasse toi de toute ces listes, les listes sont tout aussi immuables que les nombres en Haskell, et tu n'as de toute façon pas besoin de les changer...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    import Graphics.Gloss
     
    y =  0.0
    x =  4.0
    b =  1.0
    a = -0.4
     
    f =  a*x + (1-a)*2*x^2 / (1+x^2)
    x'=  0.0
    y'=  0.0
     
    main =
         do
            let x'=b*y + f
    	    f =a*x' + (1-a)*2*x'^2 / (1+x'^2)
    	    y'=f - x
                x =x'
                y =y'
            dessin
            main 
     
    picture = pictures   
    	[ (translate (10*x) (10*y) (point))
     	]
     
    myColor n = ( [ca,cb,cc,cd,ce,cf,cg,ch,ci,cj,ck,cl,cm,cn,co,cp] !! abs(round(n)) )
    ca = white
    cb = light(light yellow)
    cc = light yellow
    cd = yellow   
    ce = light(light orange)
    cf = light orange
    cg = orange
    ch = light (dark orange)
    ci = light red
    cj = red
    ck = dark red 
    cl = light violet
    cm = violet
    cn = light(light (dark violet))
    co = light ( light blue)
    cp = light blue
     
    point = color (myColor (3*f)) (circle 0.5)
     
    dessin =	
          display  
    	 (InWindow
    	       "Selle" 	 -- window title
    		(300, 300) 	 -- window size
    		(10, 10)) 	 -- window position
    	black                   -- background color
            picture                  -- picture to display
    Tu as également 18 variables déclarées pour tes couleurs que tu n'utilises que dans myColor, ils encombrent l'espace des noms inutilement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    myColor n = colors !! abs (round n)
      where colors = [
              white
              , light(light yellow)
              , light yellow
              , yellow
              , light(light orange)
              , light orange
              , orange
              , dark orange
              , light red
              , red
              , dark red
              , light violet
              , violet
              , dark violet
              , light ( light blue)
              , light blue
              ]
    (note : light (dark color) == color, à peu près, donc j'ai un peu modifié ta liste)

    Maitenant si tu veux faire une figure plus intéressante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    import Graphics.Gloss
     
    a = -0.4
    b =  1.0
     
    main = display  
    	 (InWindow
    	       "Selle" 	 -- window title
    		(300, 300) 	 -- window size
    		(10, 10)) 	 -- window position
             black                   -- background color
             picture                  -- picture to display
     
    picture = pictures (listOfPoints n x y f)
      where
        n = 100
        x = 4
        y = 0
        f =  a*x + (1-a)*2*x^2 / (1+x^2)
     
    listOfPoints 0 _ _ _ = []
    listOfPoints n x y f = point : listOfPoints (n-1) x' f' y'
      where
        x' = b*y + f
        f' = a*x' + (1-a)*2*x'^2 / (1+x'^2)
        y' = f' - x
        point = translate (10*x) (10*y) (color (myColor (3*f)) (circle 0.5))
     
    myColor n = colors !! abs (round n `mod` length colors)
      where
        colors = [
          white
          , light(light yellow)
          , light yellow
          , yellow
          , light(light orange)
          , light orange
          , orange
          , dark orange
          , light red
          , red
          , dark red
          , light violet
          , violet
          , dark violet
          , light ( light blue)
          , light blue
          ]
    Regarde comme listOfPoints() est définie et appelée initialement.

    --
    Jedaï

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 113
    Points : 64
    Points
    64
    Par défaut
    Grand merci,
    J'ai le plus grand mal à me débarrasser des habitudes du VB
    J'avais bien essayé la méthode let et la méthode where sans grand succès.
    Grace à votre aide j'ai appris concrètement sur un exemple. alors que toutes les leçons donnent
    des bribes de langage que j'ai du mal à assembler dans un code cohérant.
    Le plus évocateur de mes difficultés sont les deux lignes :

    listOfPoints 0 _ _ _ = []
    listOfPoints n x y f = point : listOfPoints (n-1) x' f' y'

    Cet étape franchie, je pourrais maintenant essayer d' ajouter le choix des paramètres de départ,
    affin d'obtenir différentes images.
    Ah, une petite modification : point = translate (10*x') (10*y') (color (myColor (3*f)) (circle 1.0)),
    pour obtenir la fractale il faut utiliser les nouvelle coordonnées x' et y'.

    Merci encore, salutations.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/06/2015, 15h06
  2. [Python 3.X] mysql.connector Problème bytearray() le même scripte mais le resultat different
    Par mondher bensalem dans le forum Général Python
    Réponses: 3
    Dernier message: 10/02/2015, 20h17
  3. resultat different entre TestNg et mvn test
    Par pcouas dans le forum Tests et Performance
    Réponses: 0
    Dernier message: 07/11/2010, 10h16
  4. difference entre les interfaces gui et les interfaces programmées à la main
    Par aichaeside dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 29/10/2009, 14h15
  5. Réponses: 7
    Dernier message: 13/12/2006, 12h57

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