2010-02-03 5 views
22

cuando divide una lista usando la sintaxis x: xs ¿por qué está entre paréntesis? ¿Cuál es el significado de los paréntesis? ¿por qué no [x: xs] o solo x: xs?¿Qué significan los paréntesis en (x: xs) cuando coinciden los patrones?

+0

¿Tiene un ejemplo de dónde está envuelto en()? x: xs se puede utilizar como está para describir una lista con el primer elemento de la lista. [x: xs] sería una lista con la lista x: xs en ella. –

+0

Él dice sobre la coincidencia de patrones, no sobre la construcción de listas. – Rorick

Respuesta

41

La célula contras no tiene que ser entre paréntesis en cada contexto, pero en la mayoría de los contextos es porque

aplicación de función se une más fuerte que cualquier operador infijo.

Grabar esto en su cerebro con letras de fuego.

Ejemplo:

length [] = 0 
length (x:xs) = 1 + length xs 

Si se omitieron paréntesis, el compilador podría pensar que tenía un argumento x seguido por un operador infijo mal colocado, y se quejaba con amargura. Por otra parte esto está bien

length l = case l of [] -> 0 
        x:xs -> 1 + length xs 

En este caso, ni tampoco xxs posiblemente puede interpretarse como parte de una aplicación de función de modo que no se necesitan paréntesis.

Tenga en cuenta que la misma aplicación maravillosa regla función se une más fuerte que cualquier operador infijo es lo que nos permite escribir length xs en 1 + length xs sin paréntesis. La regla de infijo da y la regla de infijo se quita.

+2

+1 para las cartas de fuego. Mi código Haskell dejó de parecerse a Lisp después de que internalicé esta regla. – Nefrubyr

+1

+1. Amo la última oración –

14

Simplemente está utilizando el operador de contras :, que tiene baja precedencia. Los paréntesis son necesarios para que las cosas se mantengan correctas.

Y no usa [x:xs], porque eso coincidiría con una lista cuyo único elemento es una lista con la cabecera x y la cola xs.

+1

Nunca había probado ese patrón '[x: xs]' específico, pero por supuesto tiene razón; coincide con una lista única en el nivel superior. La notación desajustada del patrón sería: '((x: xs): [])'. –

3

No sé la respuesta exacta, pero creo que eso se debe a lo que se puede combinar en los patrones. Solo los constructores pueden ser emparejados. Los constructores pueden ser de una sola palabra o compuesto. Mire el siguiente código:

data Foo = Bar | Baz Int 

f :: Foo -> Int 
f Bar  = 1 
f (Baz x) = x - 1 

Constructores de una sola palabra coinciden como están. Pero los constructores compuestos deben estar rodeados de parens para evitar la ambigüedad. Si nos saltamos parens parece que emparejan contra dos argumentos independientes:

f Baz x = x - 1 

Así que, como es (:) compuesta debe estar en parens. Saltarse los parens por Bar es un tipo de azúcar sintáctica.

ACTUALIZACIÓN: Me di cuenta de que (como señaló sykora) es una consecuencia de la precedencia del operador. Aclara mis suposiciones La aplicación de función (que es solo espacio entre función y argumento) tiene la más alta prioridad. Otros que incluyen (:) tienen precedencia más baja. Entonces, f x:xs se debe interpretar como ((:) (f x)) xs que presumiblemente no es lo que necesitamos. Mientras que f (x:xs) se interpreta como f aplicado a x:xs que es a su vez (:) aplicado a x y xs.

2

Tiene que ver con el análisis sintáctico.

Recuerde, los dos puntos: es solo un constructor que está escrito con la sintaxis del operador. Por lo tanto una función como

foo [] = 0 
foo (x:xs) = x + foo xs 

también se podría escribir como

foo [] = 0 
foo ((:) x xs) = x + foo xs 

Si se le cae el paréntesis en la última línea, se hace muy difícil de analizar!

1

: es un constructor de datos, como cualquier otra coincidencia de patrón, pero infijo escrito. Los paréntesis están puramente allí debido a la precedencia del infijo; en realidad no son necesarios y se pueden omitir con seguridad cuando las reglas de precedencia lo permiten. Por ejemplo:

> let (_, a:_) = (1, [2, 3, 4]) in a 
2 
> let a:_ = "xyzzy" 
'x' 
> case [1, 2, 3] of; a:b -> a; otherwise -> 0; 
1 

Curiosamente, eso no parece funcionar en la cabeza de una lambda. No estoy seguro por qué.

Como siempre, el operador "yuxtaposición" se une más fuerte que cualquier otra cosa, por lo que más a menudo que no los delimitadores son necesarias, pero no son en realidad parte de la coincidencia de patrón - de lo contrario no sería capaz para utilizar patrones como (x:y:zs) en lugar de (x:(y:zs)).

Cuestiones relacionadas