Question

J'essaie de déterminer si Haskell utilise une portée dynamique ou statique. Je me rends compte que, par exemple, si vous définissez:

let x = 10

puis définissez la fonction

let square x = x*x

Vous avez 2 "x" différents, et cela signifie-t-il que sa portée est dynamique? Si non, quelle portée utilise-t-il et pourquoi?

De plus, les variables Haskell peuvent-elles avoir des alias (un nom différent pour le même emplacement / valeur de mémoire)?

Merci.

Était-ce utile?

La solution

Il y a des erreurs dans vos déclarations ...

  • Il n'y a pas de variables mutables dans Haskell mais juste des définitions (ou des variables immuables)
  • Un emplacement de mémoire variable est un concept qui n'existe pas dans Haskell

Dans votre exemple, x est pas 10 dans la fonction, il s'agit simplement d'un argument en carré, pouvant prendre n'importe quelle valeur (vous pouvez spécifier le type ultérieurement). cas 10 mais juste dans ce cas.

Voici un exemple d'alias fourni par Curt Sampson :

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42

Autres conseils

Haskell utilise (en termes généraux) exactement la même portée lexicale que la plupart des autres langues.

par exemple.

x = 10

Résultats dans une valeur référencée via x dans la portée globale, alors que

square x = x * x

aura pour résultat que x sera étendu de manière lexicale au carré de la fonction. Cela peut aider si vous pensez que la forme ci-dessus est une finesse syntaxique pour:

square = \ x -> x * x

En ce qui concerne votre autre question, je ne suis pas sûr de ce que vous entendez par aliasing

Répondant uniquement à la deuxième partie de la question:

Vous pouvez avoir plusieurs alias pour le même "emplacement de mémoire", mais comme ils sont tous immuables, peu importe la plupart du temps.

Exemple muet:

foo x y = x * y
bar z = foo z z

Lorsque foo est appelé depuis la code , x et y ont clairement la même valeur. Mais comme vous ne pouvez modifier ni x ni y , vous ne le remarquerez même pas.

Comme la première partie de la question a déjà été répondue, voici la deuxième partie:

Je suppose que par aliasing , vous voulez dire un nom pour un autre . Comme haskell est un langage fonctionnel et que les fonctions se comportent comme des identifiants normaux, vous pouvez le faire comme ceci:

y = x

qui définirait un alias y pour la fonction x . Notez que tout est une fonction. Même si cela ressemble à une "variable" , il s’agit simplement d’une fonction nullary ne prenant aucun argument. Les alias des types se présentent comme suit:

type Function = Double -> Double

qui définirait un alias Fonction pour le type Double - > Double

Haskell utilise des étendues imbriquées statiques. Ce qui est un peu déroutant par rapport aux autres langages ayant des portées imbriquées statiques est que la portée d'un nom est un bloc qui inclut des tests précédant sa définition . Par exemple

evens = 0 : map (+1) odds
odds  = map : (+1) evens

Ici, le nom "cotes" figure dans la définition du mot "même", malgré le fait surprenant que "cotes" n’ait pas encore été défini. (L'exemple définit deux listes infinies de nombres pairs et impairs.)

Une langue morte avec une règle de portée similaire était Modula-3. Mais Haskell est un peu plus délicat en ce sens que vous pouvez essayer de "redéfinir" une variable dans le même périmètre, mais en introduisant simplement une autre équation de récursivité. C’est un piège pour les personnes qui ont appris le ML ou le schéma en premier:

let x = 2 * n
    x = x + 1   -- watch out!

Ceci est parfaitement bon ML ou Scheme let *, mais Haskel a une sémantique de schéma letrec, sans restriction aux valeurs lambda. Pas étonnant qu'il s'agisse de choses difficiles!

Dans votre exemple, la définition globale de x est ombrée par la définition locale de x. Dans Haskell, la portée d'une variable est déterminée par une lecture statique du code source - c'est ce qu'on appelle la portée lexicale, mais peut obtenir quelque chose de similaire à la portée dynamique avec des paramètres implicites (mais cela peut entraîner un comportement inattendu (j'ai lu; jamais essayé moi-même)).

Pour résumer les autres réponses avec concision:

  1. portée lexicale
  2. aliasing est aussi simple que x = 1; y = x , mais cela n’a généralement aucune importance, car les choses sont immuables.

La syntaxe let que vous utilisez dans votre exemple semble se trouver à l'invite interactive ghci > . Tout en mode interactif se produit au sein de la monade d’OI, de sorte que les choses peuvent sembler plus modifiables que la normale.

Eh bien, comme je pense que les gens l’ont déjà dit, Haskell n’a aucune variable comme dans la plupart des autres langues, elle n’a que des expressions. Dans votre exemple, let x = 10 x est une expression évaluée toujours à 10. Vous ne pouvez pas modifier la valeur de x ultérieurement, bien que vous puissiez utiliser les règles de portée pour le masquer en définissant x être une autre expression.

Oui, Haskell a des alias. Essayez ce petit programme:

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top