2010-10-29 16 views
5

¿Por qué la siguiente secuencia de comandos de Haskell no funciona como se esperaba?Variables en Haskell

find :: Eq a => a -> [(a,b)] -> [b] 
find k t = [v | (k,v) <- t] 

Dada find 'b' [('a',1),('b',2),('c',3),('b',4)], el intérprete vuelve [1,2,3,4] en lugar de [2,4]. La introducción de una nueva variable, a continuación denominado u, es necesario conseguir que esto funcione:

find :: Eq a => a -> [(a,b)] -> [b] 
find k t = [v | (u,v) <- t, k == u] 

¿Alguien sabe por qué la primera variante no produce el resultado deseado?

+0

Repita después de mí: no hay variables en Haskell. ;-) Estos son símbolos o identificadores. Las variables implican variabilidad. En Haskell, todo es inmutable. –

+9

@Konrad Rudolph: El Informe Haskell 98 utiliza el término "variable" en todas partes. Es importante tener en cuenta que esto no significa lo que podría esperar, pero no creo que sea más perspicaz que la documentación estándar que necesariamente es útil. –

+4

@Konrad Rudolph: ¡Seguro que bromeas! Vaya, encontré una sección completa sobre variables [en algunos Haskell, aquí] (http://books.google.com/books?id=27dkTJFrLZIC&pg=PA111). –

Respuesta

14

Desde el Haskell 98 Report:

Como de costumbre, los enlaces en la lista por comprensión pueden remedar las de ámbitos exteriores; por ejemplo:

[ x | x <- x, x <- x ] = [ z | y <- x, z <- y]

Otro punto: si se compila con -Wall (o específicamente con -fwarn-name-shadowing) obtendrá la siguiente advertencia:

Warning: This binding for `k' shadows the existing binding 
      bound at Shadowing.hs:4:5 

Usando -Wall es generalmente una buena idea: a menudo resaltará lo que está sucediendo en situaciones potencialmente confusas como esta.

+0

+1 para la sugerencia de indicador de citación y advertencia –

+0

Creo que el problema no es sobre sombreado.Se trata, en primer lugar, del significado de un identificador en un patrón: no coincide con el valor de una variable con ese identificador, sino que coincide con cualquier cosa y vincula el valor a una nueva variable con ese idenfier. – newacct

11

La coincidencia de patrón (k,v) <- t en el primer ejemplo crea dos nuevas variables locales y vk que se rellenan con el contenido de la tupla t. La coincidencia de patrón no compara el contenido de t con la variable existente k, sino que crea una nueva variable k (que oculta la externa).

En general, nunca ocurre una "sustitución de variables" en un patrón, cualquier nombre de variable en un patrón siempre crea nuevas variables locales.

3

Sólo puede coincidir con el patrón en literales y constructores.
No puede coincidir en las variables. Leer más here.

Dicho esto, puede que le interesen los patrones de visualización.