161 votos

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

Me encontré con la siguiente definición como yo trato de aprender Haskell usando un proyecto real para conducirlo. No entiendo por qué el signo de exclamación delante de cada argumento significa y mis libros no parecía mencionarlo.

 data MidiMessage = MidiMessage !Int !MidiMessage
 

192voto

Curt Sampson Puntos 10866

Es un rigor de la declaración. Básicamente, esto significa que debe ser evaluado a lo que se llama "débil normal de la forma de la cabeza" cuando la estructura de datos se crea valor. 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, se devolverá un "thunk": es decir, el código a ejecutar para averiguar su valor. En ese momento, un Foo aún no existe todavía, sólo el código.

Pero en algún momento alguien puede probar a buscar dentro de ella, 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 se va a ejecutar el código necesario para hacer lo que necesita, y no más. Por lo que se cree un Foo con cuatro parámetros (porque no se puede mirar en su interior sin que las existentes). La primera, debido a que tenemos las pruebas, tenemos que evaluar todo el camino a 4, donde nos damos cuenta de que no coincide.

El segundo no necesitan ser evaluados, porque no estamos de pruebas. Así, en lugar de 6 está almacenado en la ubicación de la memoria, sólo tendremos que almacenar el código para la posterior evaluación, (3+3). Que se convertirá en un 6 sólo si alguien los mira.

El tercer parámetro, sin embargo, tiene un ! frente a ella, por lo que es estrictamente evaluados: (4+4) es ejecutado, y 8 está almacenado en la ubicación de la memoria.

El cuarto parámetro es también estrictamente evaluados. Pero aquí es donde se pone un poco complicado: que estamos evaluando no totalmente, pero sólo a la debilidad de la normal de la forma de la cabeza. Esto significa que hemos de averiguar si es Nothing o Just algo, y la tienda, pero nosotros, sin ir más lejos. Eso significa que nosotros no almacenar Just 10 pero en realidad, Just (5+5), dejando el procesador en el interior sin evaluar. Es importante saber esto, aunque creo que todas las implicaciones que esto vaya más allá del alcance de esta pregunta.

Puede anotar los argumentos de la función de la misma manera, si se activa el BangPatterns de extensión de lenguaje:

f x !y = x*y

f (1+1) (2+2) devolverá el código thunk (1+1)*4.

42voto

Chris Conway Puntos 24671

Una forma sencilla de ver la diferencia entre argumentos del constructor estrictos y no estrictos es cómo se comportan cuando están sin definir. Dada

 data Foo = Foo Int !Int

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

Dado que el argumento no estricto no es evaluada por second , pasando en undefined no causa un problema:

 > second (Foo undefined 1)
1
 

Pero el argumento no puede ser estricta undefined , incluso si no utilizamos el valor:

 > first (Foo 1 undefined)
*** Exception: Prelude.undefined
 

22voto

Chris Vest Puntos 5622

Creo que es una anotación de rigor.

Haskell es un lenguaje funcional puro y perezoso, pero a veces la sobrecarga de pereza puede ser demasiado o derrochador. Así que lidiar con eso, usted puede pedir que compilador para evaluar plenamente los argumentos a una función en lugar de analizar thunks alrededor.

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

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X