patrones otherwise haskell syntax

patrones - otherwise haskell



¿Qué significan los paréntesis en(x: xs) cuando coinciden los patrones? (5)

cuando divides una lista usando la sintaxis x: xs, ¿por qué está envuelta entre paréntesis? ¿Cuál es el significado de los paréntesis? ¿por qué no [x: xs] o simplemente x: xs?


La celda de contras no tiene que estar entre paréntesis en todos los contextos, pero en la mayoría de los contextos es porque

La aplicación de la función se enlaza más fuerte que cualquier operador de infijo.

Quema esto en tu cerebro con letras de fuego.

Ejemplo:

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

Si se omitieran paréntesis, el compilador pensaría que tenía un argumento x seguido de un operador de infijo mal colocado, y se quejaría amargamente. Por otro lado esto está bien.

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

En este caso, ni x ni xs pueden interpretarse como parte de una aplicación de función, por lo que no se necesitan paréntesis.

Tenga en cuenta que la misma aplicación de función de regla maravillosa se enlaza más fuerte que cualquier operador de 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.


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

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

Los constructores de una sola palabra coinciden como están. Pero los constructores compuestos deben estar rodeados de paréntesis para evitar la ambigüedad. Si nos saltamos los parens, parece que coinciden con dos argumentos independientes :

f Baz x = x - 1

Entonces, como (:) es compuesto debe estar en parens. Saltarse parens para Bar es un tipo de azúcar sintáctico.

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 el espacio entre la función y el argumento) tiene la mayor prioridad. Otros que incluyen (:) tienen menor prioridad. Así que fx:xs debe interpretarse como ((:) (fx)) xs que probablemente no es lo que necesitamos. Mientras que f (x:xs) se interpreta como f aplicado a x:xs que a su vez (:) aplica a x y xs .


Simplemente estás usando el operador contras : que tiene poca prioridad. Se necesitan paréntesis para que las cosas se mantengan bien.

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


Tiene que ver con el análisis.

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

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

También podría ser escrito como

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

Si coloca el paréntesis en la última línea, ¡es muy difícil analizarlo!


: 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 infijo; en realidad no son necesarios y se pueden omitir de forma segura 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 un lambda. No estoy seguro de por qué.

Como siempre, el operador de "yuxtaposición" se enlaza más fuerte que cualquier otra cosa, por lo que la mayoría de las veces los delimitadores son necesarios, pero en realidad no son parte de la coincidencia del patrón; de lo contrario, no sería posible utilizar patrones como (x:y:zs) lugar de (x:(y:zs)) .