2011-07-24 21 views
19

Soy muy nuevo en Haskell. ¿Podría alguien explicar por qué la definición de una lista como esta devuelve una lista nulaDisminución de rangos en Haskell

ghci> let myList = [10..1] 
ghci> myList 
[] 

Sin embargo, esto funciona correctamente.

ghci> let myList = [10, 9..1] 
ghci> myList 
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] 

Respuesta

34

Básicamente, porque [10..1] se traduce a enumFromTo 10 1 que en sí mismo tiene la semántica para crear una lista mediante la adopción de todos los elementos menos-que 1 que resultan de contar hacia arriba (con el paso de tamaño +1) a partir de (incluyendo) 10.

Considerando [10, 9..1] se traduce a enumFromToThen 10 9 1 que se explicita el conteo de paso de tamaño como 9-10, es decir -1 (que está codificada a +1 para enumFromTo)

una especificación más exacta se puede encontrar en el informe de Haskell (6.3.4 El Enum Class):

enumFrom  :: a -> [a]   -- [n..] 
enumFromThen :: a -> a -> [a]  -- [n,n'..] 
enumFromTo  :: a -> a -> [a]  -- [n..m] 
enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m] 

Para los tipos Int y Integer, las funciones de enumeración hav e el siguiente significado:

  • La secuencia enumFrom e1 es la lista [e1,e1+1,e1+2,...].

  • La secuencia enumFromThen e1 e2 es la lista [e1,e1+i,e1+2i,...], donde el incremento, i, es e2-e1. El incremento puede ser cero o negativo. Si el incremento es cero, todos los elementos de la lista son iguales.

  • La secuencia enumFromTo e1 e3 es la lista [e1,e1+1,e1+2,...e3]. La lista está vacía si e1 > e3.

  • La secuencia enumFromThenTo e1 e2 e3 es la lista [e1,e1+i,e1+2i,...e3], en donde el incremento, i, es e2-e1. Si el incremento es positivo o cero, la lista finaliza cuando el siguiente elemento sea mayor que e3; la lista está vacía si e1 > e3. Si el incremento es negativo, la lista finaliza cuando el siguiente elemento sea menor que e3; la lista está vacía si e1 < e3.

+0

Gracias, esto tiene sentido. A primera vista, pensé que era una notación bastante tonta, pero ahora puedo ver que permite definir el tamaño de los pasos en el rango. ¡Muy genial! Muy entusiasmado con Haskell ahora :) – Christopher

11

notación secuencia aritmética es sólo azúcar sintáctico para las funciones de la clase Enum.

[a..]  = enumFrom a 
[a..b] = enumFromTo a b 
[a, b..] = enumFromThen a b 
[a, b..c] = enumFromThenTo a b c 

En cuanto a por qué no se han definido para revertir de forma automática, sólo puedo especular, pero aquí hay algunas razones posibles:

  • Si a y b están definidos en otro lugar, sería más difícil de decir de un vistazo en qué dirección iría [a..b].

  • Tiene mejores propiedades matemáticas para razonar.No tiene que agregar casos especiales para cuando se revertirá la secuencia.

2

Si desea generar una lista a-b independientemente de si a < b, puede utilizar el siguiente:

[a, a + (signum $ b - a)..b]

+1

Tenga en cuenta que esto produce una lista infinita si 'a = b'. – hammar

+0

@hammar Me encuentro corregido :) – dionyziz