haskell layout rules

Perplejo por cómo este código es procesado por la instalación de Layout de Haskell



rules (1)

Mientras navegaba por https://wiki.haskell.org/IO_inside , encontré el siguiente comentario y código ...

"Además, las reglas de diseño de Haskell nos permiten usar el siguiente diseño:

main = do a <- readLn if (a>=0) then return () else do print "a is negative" ...

eso puede ser útil para escapar del medio de una declaración de "hacer" larga. "

A partir de ahora, usaré el símbolo C * para referirme al código anterior.

Supongo que la intención de C * es leer en un número, y luego:
(i) Si no es negativo, no haga nada.
(ii) Si es negativo, muestre el resultado indicando que sí lo es.

Mi reacción inicial fue pensar que C * o bien no se analizaría correctamente o no se comportaría como se esperaba.

Pensé que Layout insertaría un conjunto vacío de llaves y un punto y coma inmediatamente después del segundo ''do'' porque el lexema ''imprimir'' no está sangrado más que el nivel de sangría del contexto de disposición actual establecido por ''a'' en "a < - readLn ".

Es decir, mi predicción para el código insensible al diseño (en lo sucesivo, denominado C '') generado por Layout sería algo así como:

main = do { a <- readLn; if (a>=0) then return () else do {}; print "a is negative" ... }

Que yo pensé que este sería el caso, se basó en la siguiente frase contenida en la sección 2.7 (''Estructura léxica'': ''Diseño'') de la Parte 1 del Informe del idioma Haskell 2010 ( https://www.haskell.org/onlinereport/haskell2010/haskellpa1.html ):

"Si la sangría del lexema sin corchete inmediatamente después de where, let, do o es menor o igual que el nivel de sangría actual, en lugar de comenzar un diseño, se inserta una lista vacía" {} "y el diseño el procesamiento ocurre para el nivel actual (es decir, inserte un punto y coma o un corsé cerrado) ".

En la sección 10.3 (''Referencia de sintaxis'': ''Diseño'') de la Parte 1 (URL dada anteriormente) se proporciona una descripción más detallada de las reglas de diseño en Haskell 2010 Language Report.

Al leer esta cuenta más detallada, me sentí seguro de que mi predicción para el código insensible al diseño generado por Layout (es decir, C '') era correcta.

Sin embargo, para mi sorpresa, cuando probé el código original estipulado anteriormente (es decir, C *) en GHCi, funcionó (se analizó correctamente y se comportó como se esperaba).

Preguntas ...

  1. ¿Es correcta la oración que cité arriba (de la sección 2.7)?

  2. ¿Es precisa la cuenta detallada de las reglas de diseño mencionadas anteriormente (de la sección 10.3)?

  3. ¿Cuál es la (s) falla (s) en el razonamiento que empleé para llegar a mi predicción para el código insensible al diseño (es decir, C '') generado por Layout para el código original C *?

  4. ¿Cuál es el código insensible al diseño producido por Layout para el código original estipulado anteriormente (es decir, para C *) y cuáles son las reglas / principios que lo explican?

  5. En general, ¿hay alguna manera de que pueda ver el código insensible al diseño generado por Layout? Si es así, ¿qué es (por favor detalla / explica la técnica a un nivel adecuado para alguien nuevo en Haskell, como yo)?


Esta es una desviación conocida y documentada de GHC del estándar Haskell en modo predeterminado o Haskell 98.

GHC tiene una extensión de lenguaje llamada NondecreasingIndentation que se puede usar para desencadenar este comportamiento. Si está habilitado, una palabra clave do introduce un nuevo bloque incluso si el siguiente token comienza en el mismo nivel de sangría que el bloque circundante.

Si no quiere esto, diga -XNoNondecreasingIndentation o -XHaskell2010 (o utilice los pragmas de idioma en consecuencia).

Puede ver una versión bastante impresa del código que analizó GHC pasando el -ddump-parsed a GHC. Esto solo eliminará parcialmente el diseño (lo hace para do-blocks, pero por ejemplo, no para dejarlo), pero podría proporcionar pistas.