¿Qué significa el signo de exclamación en una declaración de Haskell?


Me encontré con la siguiente definición mientras intento aprender Haskell usando un proyecto real para conducirlo. No entiendo lo que significa el signo de exclamación delante de cada argumento y mis libros no parecían mencionarlo.

data MidiMessage = MidiMessage !Int !MidiMessage
Author: svick, 2009-06-14

3 answers

Es una declaración estricta. Básicamente, significa que debe ser evaluado a lo que se llama "forma de cabeza normal débil" cuando se crea el valor de la estructura de datos. Veamos un ejemplo, para que podamos ver lo que esto significa:

data Foo = Foo Int Int !Int !(Maybe Int)

f = Foo (2+2) (3+3) (4+4) (Just (5+5))

La función f anterior, cuando se evalúa, devolverá un "tonk": es decir, el código a ejecutar para averiguar su valor. En ese momento, un Foo ni siquiera existe todavía, solo el código.

Pero en algún momento alguien puede tratar de mirar dentro esto, probablemente a través de una coincidencia de patrón:

case f of
     Foo 0 _ _ _ -> "first arg is zero"
     _           -> "first arge is something else"

Esto va a ejecutar suficiente código para hacer lo que necesita, y no más. Por lo tanto, creará un Foo con cuatro parámetros (porque no puede mirar dentro de él sin que exista). El primero, ya que lo estamos probando, necesitamos evaluar todo el camino hasta 4, donde nos damos cuenta de que no coincide.

El segundo no necesita ser evaluado, porque no lo estamos probando. Por lo tanto, en lugar de que 6 se almacene en esa ubicación de memoria, almacene el código para una posible evaluación posterior, (3+3). Eso se convertirá en un 6 solo si alguien lo mira.

El tercer parámetro, sin embargo, tiene un ! delante de él, por lo que se evalúa estrictamente: (4+4) se ejecuta, y 8 se almacena en esa ubicación de memoria.

El cuarto parámetro también se evalúa estrictamente. Pero aquí es donde se pone un poco complicado: estamos evaluando no completamente, sino solo a la forma normal débil de la cabeza. Esto significa que averiguamos si es Nothing o Just algo, y almacenar eso, pero no vamos más allá. Eso significa que no almacenamos Just 10 sino en realidad Just (5+5), dejando el tonk dentro sin evaluar. Es importante saber esto, aunque creo que todas las implicaciones de esto van más allá del alcance de esta pregunta.

Puede anotar argumentos de función de la misma manera, si habilita la extensión de idioma BangPatterns:

f x !y = x*y

f (1+1) (2+2) devolverá el tonk (1+1)*4.

 271
Author: Curt J. Sampson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-14 17:52:18

Una forma sencilla de ver la diferencia entre los argumentos de constructor estrictos y no estrictos es cómo se comportan cuando no están definidos. Dado

data Foo = Foo Int !Int

first (Foo x _) = x
second (Foo _ y) = y

Dado que el argumento no estricto no es evaluado por second, pasar undefined no causa un problema:

> second (Foo undefined 1)
1

Pero el argumento estricto no puede ser undefined, incluso si no usamos el valor:

> first (Foo 1 undefined)
*** Exception: Prelude.undefined
 74
Author: Chris Conway,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-14 22:30:32

Creo que es una anotación estricta.

Haskell es un lenguaje funcional puro y perezoso , pero a veces la sobrecarga de la holgazanería puede ser demasiado o derrochadora. Así que para lidiar con eso, puedes pedirle al compilador que evalúe completamente los argumentos de una función en lugar de analizar los thunks.

Hay más información en esta página: /Rendimiento Rigor.

 24
Author: Chris Vest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-14 16:12:06