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 :

Comment saisir au clavier une "variable globale" ?


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 Comment saisir au clavier une "variable globale" ?
    Bonjour,
    Comment saisir au clavier des "variables globales" pouvant être utilisées dans l'ensemble de programme et pas en tant que l'argument à transmettre ?
    Dans les autres langages on désigne les variables comme globales dans un module de base et on peut leur donner une valeur au clavier n'import ou et les utiliser aussi.
    Comment faire ça en Haskell ?
    Merci d'avance.
    Pour l'instant je n'ai qu'une idée : utiliser une function prompt (ou autre)
    Main = do
    s <- prompt "donnez une valeur a s"
    Puis enregistrer s dans un fichier et lire quant on a besoin.
    Je cherche une solution plus simple, sans accès au disque.
    Par example Data.Global IORef, mais comment indiquer sa valeur a partir du clavier?

  2. #2
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : avril 2013
    Messages : 610
    Points : 1 880
    Points
    1 880
    Billets dans le blog
    21
    Par défaut
    C'est presqu'impossible pour une bonne raison (si du moins on adopte l'approche Haskell), qui est la pureté fonctionnelle du langage: le résultat d'une fonction ne peut pas dépendre d'autre chose que de ses arguments.

    Votre solution par l'accès au disque ne change pas fondamentalement le problème puisque, une fois lue dans le fichier, il vous faudra bien passer la valeur en argument à la fonction suivante.

    Effectivement il y a la solution IORef mais elle n'est pas d'un emploi plus aisé ou plus élégant qu'un paramètre supplémentaire à la fonction utilisée. Il y a également (plus conforme à l'esprit Haskell) la monade Reader (https://hackage.haskell.org/package/...ad-Reader.html) mais c'est déjà une notion plus avancée, d'autant qu'il faudra la combiner avec la monade IO pour l'initialiser avec une entrée utilisateur...

    Mais peut-être qu'avec quelques renseignements supplémentaires sur le contexte de la question, quelqu'un pourrait vous proposer une solution plus efficace.

  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
    Merci pour votre réponse, elle correspond aux renseignements glanés sur le net. Si je lit sur le disque ca sera justement au sain de la function qui en a besoin et ne sera jamais transmis à une autre.
    En occurence il s'agit du diviseur qui détermine la palette de couleur pour chaque point d'une fractale complexe (Mandelbrot, Julia, Burning ship et Newton). Je n'arrive pas à transmettre ce diviseur en tant qu'argument (pour ces programmes uniquement). Vous pouvez voir le code pour Burning ship dans mon poste le concernant. J'ai donné l'explication de l'utilisation de ce diviseur sur http://haskellaskvasil.wordpress.com Complexes.

  4. #4
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : avril 2013
    Messages : 610
    Points : 1 880
    Points
    1 880
    Billets dans le blog
    21
    Par défaut
    Pour la solution de lecture d'un fichier (outre le fait que c'est lent), il ne faut pas oublier que la monade IO est une "one-way monad", c'est-à- dire qu'on ne peut pas en sortir une fois entré. La fonction qui utilise cette palette devra donc avoir un type de retour en conséquence (avec IO dedans) et donc ses valeurs de sortie avoir ce type pour que le compilateur les accepte.

    En regardant le code de "Complexe" sur votre blog, je ne vois pas de difficulté à passer le diviseur depuis main jusqu'à t en passant par drawJulia et allPoints, même s'il est vrai que ça ne paraît pas très élégant. Cela étant les autres possibilités ne sont guère plus jolies... Si vous rencontrez un problème technique pour passer le diviseur en argument, quel est-il?

  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
    Désole, mais je n'arrive pas. Un fois le s saisi dans le main j'ai beau essayer de le transmettre jusqu'au î/s, rien ne marche. Je commet forcément des erreurs qui me dépassent. Alors si en plus je veux definir le zoom au clavier.. .

  6. #6
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : avril 2013
    Messages : 610
    Points : 1 880
    Points
    1 880
    Billets dans le blog
    21
    Par défaut
    Voilà, j'ai modifié ton code, le diviseur est le premier argument en ligne de commande.

    Code Haskell : 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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    import Graphics.Rendering.OpenGL
    import Graphics.UI.GLUT
    import Data.IORef
    data Complex = C (Float, Float) deriving (Show,Eq)
     
    instance Num Complex where
    	fromInteger n = C (fromIntegral n, 0.0)
    	C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
    	C (x,y) + C (z,t) = C (x+z, y+t)
    	abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
    	signum (C (x,y))  = C (signum x , 0.0)
     
    complex :: Float -> Float -> Complex
    complex x y = C (x,y)
     
    real :: Complex -> Float
    real (C (x,y))    = x
     
    im :: Complex -> Float
    im   (C (x,y))    = y
     
    magnitude :: Complex -> Float
    magnitude = real.abs
     
    main :: IO ()
    main = do
    	(progname,(x:xs)) <- getArgsAndInitialize
    	initialDisplayMode $= [DoubleBuffered]
    	initialWindowSize $= Size 320 320
    	createWindow "Julia Set 1"
    	let div = realToFrac . read $ x
    	displayCallback $= display div
    	print "PATIENTEZ !!!"
    	display div
    	mainLoop
     
    display :: GLfloat -> IO ()
    display n = do
    	clear [ColorBuffer] -- make the window black
    	loadIdentity -- reset any transformation
    	preservingMatrix (drawJulia n)
    	swapBuffers -- refresh screen
    	flush
     
     
    drawJulia :: GLfloat -> IO ()
    drawJulia n = renderPrimitive Points $ do
    	mapM_ drawColoredPoint (allPoints n)
    	where
    		drawColoredPoint (x,y,z) = do
    		color z -- set the current color to c
    		vertex $ Vertex3 x y 0
     
    width = 200 :: GLfloat
    height = 200 :: GLfloat
     
    allPoints :: GLfloat -> [(GLfloat,GLfloat,Color3 GLfloat)]
    allPoints n = [ (x/width, y/height, (colorFromValue n (julia x y))) | x <- [-width..width], y <- [-height..height]]
     
    colorFromValue :: GLfloat -> Int -> Color3 GLfloat
    colorFromValue d n = let
    		t :: Int -> GLfloat
    		t i = 0.5 + 0.5*sin( fromIntegral i/d)
    	in
    		Color3 (t n) (t (n+5)) (t (n+10))
     
    julia :: GLfloat -> GLfloat -> Int
    julia x y = let 
    		r = realToFrac $ 0.2 * x / width
    		i = realToFrac $ 0.2 * y / height
    		s = -0.7
    		p = 0.2715
    	in
    		f (complex s p) (complex r i) 128
     
    f :: Complex -> Complex -> Int -> Int
    f c z 0 = 0
    f c z n = if (magnitude z > 2 ) then n else f c ((z*z)+c) (n-1)

  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
    Ok, mais comment le lancer dans winGHCi car :
    *** Exception: user error (Pattern match failure in do expression at MonJuliaSet.hs:27:9-25)
    Mais j'ai réussi en substituant mes fonction de saisie au read. Voici Mandelbrot, pour les autres complexes ça sera pareil.

    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    import Graphics.Rendering.OpenGL
    import Graphics.UI.GLUT
    import Data.IORef
     
    data Complex = C (Float, Float) deriving (Show,Eq)
     
    instance Num Complex where
        fromInteger n = C (fromIntegral n,0.0)
        C (x,y) * C (z,t) = C (z*x - y*t, y*z + x*t)
        C (x,y) + C (z,t) = C (x+z, y+t)
        abs (C (x,y))     = C (sqrt (x*x + y*y),0.0)
        signum (C (x,y))  = C (signum x , 0.0)
     
    complex :: Float -> Float -> Complex
    complex x y = C (x,y)
     
    real :: Complex -> Float
    real (C (x,y))    = x
     
    im :: Complex -> Float
    im   (C (x,y))    = y
     
    magnitude :: Complex -> Float
    magnitude = real.abs
     
    main :: IO ()
    main = do
      (progname,_) <- getArgsAndInitialize
      initialDisplayMode $= [DoubleBuffered]
      initialWindowSize $= Size 320 320
      createWindow "Mandelbrot Set"
      s <- prompt "Choisissez le set Couleur:"
      displayCallback $= display s
      putStr "PATIENTEZ - La fenetre avec l'image sera affichee a la fin du traitement"
      --display d
      mainLoop
     
    display d = do
      clear [ColorBuffer] -- make the window black
      loadIdentity -- reset any transformation
      preservingMatrix (drawMandelbrot d)
      swapBuffers -- refresh screen
     
     
    drawMandelbrot d  =
      renderPrimitive Points $ do
        mapM_ drawColoredPoint (allPoints d)
      where
          drawColoredPoint (x,y,c) = do
              color c -- set the current color to c
              vertex $ Vertex3 x y 0
     
    width = 320 :: GLfloat
    height = 320 :: GLfloat
     
    --allPoints :: [ GLfloat,GLfloat, Color3 GLfloat)]
    allPoints d  = [ ((x)/width,y/height, (colorFromValue d (mandel x y ))) | 
                      x <- [-width..width], 
                      y <- [-height..height]]
     
    colorFromValue d n =
      let 
          t :: Int -> GLfloat
          t i = 0.5 + 0.5*sin( fromIntegral i / d )
      in
        Color3 (t n) (t (n+5)) (t (n+10))
     
    mandel x y  = 
      let r = realToFrac $ 2 * x / width 
          i = realToFrac $ 2 * y / height
      in
          f (complex r i) 0 64
     
    f :: Complex -> Complex -> Int -> Int
    f c z 0 = 0
    f c z n = if (magnitude z > 2 ) 
              then n
              else f c ((z*z) + c) (n-1)
     
    prompt :: String -> IO GLfloat
    prompt s = do 
    	putStrLn s
    	readLn
     
    sss :: IO (GLfloat)	  
    sss = do 
    	putStrLn "entrez numero du s" 
    	s <- readLn
    	return (s)
    Merci pour votre aide, salutations.

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

Discussions similaires

  1. [C#] Comment créer une variable globale?
    Par FraktaL dans le forum Windows Forms
    Réponses: 8
    Dernier message: 10/05/2017, 14h10
  2. Réponses: 2
    Dernier message: 21/01/2010, 17h02
  3. [sql] comment utiliser une variable global
    Par imedg dans le forum Oracle
    Réponses: 21
    Dernier message: 02/05/2006, 15h21
  4. Comment déclarer une variable globale
    Par davkick dans le forum C
    Réponses: 13
    Dernier message: 20/05/2005, 18h50

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