2008-12-02 13 views
6

Estoy tratando de averiguar si Haskell utiliza el alcance dinámico o estático. Soy consciente de que, por ejemplo, si se define:¿Qué tipo de alcance usa Haskell?

let x = 10 

entonces definir la función

let square x = x*x 

usted tiene "x" de 2 diferentes, y qué significa que está en el ámbito de forma dinámica? 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.

+2

Por cierto, Sev, es posible que desee volver a considerar si usted todavía quiere mantener la respuesta de igorgue como la aceptada para esta pregunta, ya que se ha demostrado equivocado en el punto de aliasing (ver el responda abajo) y, aunque hay argumentos al respecto, no puede encontrar ningún argumento de que no esté equivocado en el punto de las variables. –

Respuesta

5

Hay algunas cosas mal en sus estados de cuenta ...

  • no hay variables mutables en Haskell sólo las definiciones (o variables inmutables)
  • una posición de memoria variable es un concepto que no existe en Haskell

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

Aquí es un ejemplo de alias proporcionada 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 
+5

Ciertamente, Haskell tiene variables. Ver http://stackoverflow.com/questions/993124/does-haskell-have-variables/993126 –

+2

no, no tiene variables !, "definiciones" es el término correcto, o si le gusta llamarlas variables, entonces son variables inmutables como en Erlang. Todavía esto es muy diferente del concepto imperativo de "variables". – igorgue

+3

igorgue, si usted cree que Haskell no tiene variables, por favor publique una respuesta a la pregunta vinculada anteriormente y díganos por qué no lo hace. Incluya la "definición" de 'x' en' f x = x * 2'. –

11

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

por ejemplo.

x = 10 

resulta en un valor de referencia a través de x en el ámbito global, mientras que

square x = x * x 

resultará en x siendo ámbito léxico a la plaza función. Puede ayudar si se piensa en la forma anterior siendo una sutileza sintáctica para:

square = \ x -> x * x 

En cuanto a su otra pregunta no estoy seguro de lo que entendemos por aliasing

6

Respondiendo sólo la segunda parte de la pregunta:

Puede tener varios alias para el mismo "lugar de memoria", pero ya que son todos inmutables, no importa la mayor parte del tiempo.

ejemplo Dumb:

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

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

3

Como la primera parte de la pregunta ya está contestada por los demás, aquí está la segunda parte:

Asumo por aliasing quiere decir one name for another. Como Haskell es un lenguaje funcional, y las funciones se comportan como identificadores normales en cualquier caso, se puede hacer que de esta manera:

y = x 

que definiría un alias para la función yx. Tenga en cuenta que todo es una función. Incluso si parece una "variable", es solo una función nulary sin argumentos. Alias ​​para tipos aspecto:

type Function = Double -> Double 

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

+1

"una función nulary sin argumentos" - Solo me gustaría señalar que estos comentarios no son ciertos en el caso de los valores no ampliados. – porges

2

En su ejemplo, la definición global de X es la sombra de 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 ámbito léxico, pero puede obtener algo similar al alcance dinámico con parámetros implícitos (pero eso puede conducir a un comportamiento inesperado (lo he leído; probé yo mismo)).

1

Para resumir las otras respuestas concisa:

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

La sintaxis let que utiliza en su ejemplo parece que está 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.

0

Bueno, como creo que la gente ya lo ha dicho, Haskell no tiene ninguna variable como la que 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. En realidad, no puede cambiar el valor de x más adelante, aunque puede usar las reglas de ámbito para ocultarlo definiendo x como otra expresión.

+0

Los he probado, y el comportamiento es realmente bastante claro, porque necesita declarar explícitamente variables de ámbito dinámico en la definición de tipo si las usa. –

2

Haskell utiliza ámbitos anidados estáticos. Lo que es un poco confuso en comparación con otros lenguajes 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 de 'probabilidades' está en el ámbito de la definición de 'iguala', a pesar del hecho sorprendente de que 'odds' aún no ha sido definida. (El ejemplo define dos listas infinitas de números pares e impares).

Un lenguaje inactivo con una regla de ámbito similar era Modula-3. Pero Haskell es un poco más complicado en el sentido de que puede intentar 'redefinir' una variable dentro del mismo ámbito, pero en su lugar, simplemente introduce otra ecuación de recursión. Esta es una trampa para la gente que aprendió LD o el Esquema primera:

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

Esto es perfectamente buena LD o el Esquema dejó *, pero tiene Haskel esquema letrec semántica, sin la restricción a los valores de lambda. ¡No es de extrañar que esto sea algo complicado!

+0

Err ... Creo que quiere decir que el alcance "incluye otras definiciones después de la definición", o algo así, ¿no? –

+0

@Curt: Interpreto que quiere decir que el alcance de la definición de "odds" incluye la parte anterior del bloque, donde está interpretando de otra manera, con el * use * de "odds" buscado, incluidas las definiciones posteriores. –

+0

¿Es posible acceder a variables locales fuera del alcance donde están declaradas? –

0

Sí, Haskell tiene alias. Prueba 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 
Cuestiones relacionadas