Pregunta

Estoy tratando de averiguar si Haskell usa un alcance dinámico o estático. Me doy cuenta de que, por ejemplo, si define:

let x = 10

luego defina la función

let square x = x*x

Tienes 2 '' x '' diferentes, ¿y eso significa que tiene un alcance dinámico? Si no, ¿qué alcance utiliza y por qué?

Además, ¿pueden las variables Haskell tener alias (un nombre diferente para la misma ubicación / valor de memoria)?

Gracias.

¿Fue útil?

Solución

Hay algunas cosas incorrectas en sus declaraciones ...

  • No hay variables mutables en Haskell, solo definiciones (o variables inmutables)
  • Una ubicación de memoria variable es un concepto que no existe en Haskell

En su ejemplo, x es no 10 en la función es solo un argumento al cuadrado, que puede tomar cualquier valor (puede especificar el tipo más adelante) en este caso 10 pero solo en este caso.

Aquí hay un ejemplo de alias proporcionado por 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

Otros consejos

Haskell usa (en términos generales) exactamente el mismo alcance léxico que la mayoría de los otros idiomas.

ej.

x = 10

Resultados en un valor referenciado a través de x en el alcance global, mientras que

square x = x * x

dará como resultado que x tenga un alcance léxico en el cuadrado de la función. Puede ayudar si piensa que la forma anterior es una característica sintáctica para:

square = \ x -> x * x

En cuanto a su otra pregunta, no estoy seguro de qué quiere decir con aliasing

Respondiendo solo la segunda parte de la pregunta:

Puede tener varios alias para la misma " ubicación de memoria " ;, pero como todos son inmutables, no importa la mayor parte del tiempo.

Ejemplo tonto:

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

Cuando dentro de foo llamado desde bar , tanto x como y son claramente el mismo valor. Pero como no puede modificar x o y , ni siquiera lo notará.

Como la primera parte de la pregunta ya ha sido respondida por otros, aquí está la segunda parte:

Supongo que por aliasing te refieres a un nombre por otro . Como haskell es un lenguaje funcional, y las funciones se comportan como identificadores normales en cualquier caso, puede hacerlo así:

y = x

que definiría un alias y para la función x . Tenga en cuenta que todo es una función. Incluso si parece una " variable " , es solo una función nulary que no toma argumentos. Los alias para tipos se ven así:

type Function = Double -> Double

que definiría un alias Function para el tipo Double - > Doble

Haskell utiliza ámbitos anidados estáticos. Lo que es un poco confuso en comparación con otros idiomas que tienen ámbitos anidados estáticos es que el alcance de un nombre es un bloque que incluye pruebas que preceden a su definición . Por ejemplo

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

aquí el nombre 'probabilidades' está dentro del alcance en la definición de 'pares', a pesar del sorprendente hecho de que 'probabilidades' aún no se ha definido. (El ejemplo define dos listas infinitas de números pares e impares).

Un lenguaje muerto con una regla de alcance similar fue Modula-3. Pero Haskell es un poco más complicado ya que puede intentar 'redefinir' una variable dentro del mismo alcance, pero en su lugar simplemente introduce otra ecuación de recursión. Esta es una trampa para las personas que aprendieron ML o Scheme primero:

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

Esto es perfectamente bueno ML o Scheme let *, pero Haskel tiene una semántica de esquema letrec, sin la restricción de los valores lambda. ¡No es de extrañar que esto sea complicado!

En su ejemplo, la definición global de x está sombreada por la definición local de x. En Haskell, el alcance de una variable está determinado por una lectura estática del código fuente, esto se llama alcance léxico, pero puede obtener algo similar al alcance dinámico con parámetros implícitos (pero eso puede conducir a un comportamiento inesperado (he leído; nunca lo intenté yo mismo)).

Para resumir las otras respuestas de manera concisa:

  1. alcance léxico
  2. aliasing es tan fácil como x = 1; y = x pero generalmente no importa porque las cosas son inmutables.

La sintaxis let que usa en su ejemplo parece estar en el indicador interactivo ghci > . Todo en el modo interactivo ocurre dentro de la mónada IO, por lo que las cosas pueden parecer más mutables allí de lo normal.

Bueno, como creo que la gente ya ha dicho, Haskell no tiene ninguna variable como se encuentra en la mayoría de los otros idiomas, solo tiene expresiones. En su ejemplo, let x = 10 x es una expresión que siempre se evalúa como 10. No puede cambiar el valor de x más adelante, aunque puede usar las reglas de alcance para ocultarlo definiendo x ser otra expresión.

Sí, Haskell tiene alias. Pruebe este pequeño programa:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top