Es una declaración de rigor. Básicamente, significa que debe evaluarse a lo que se llama "forma normal de cabeza 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 "thunk": es decir, el código a ejecutar para calcular su valor. En ese momento, un Foo aún no existe, solo el código.
Pero en algún momento alguien puede intentar mirar dentro de él, probablemente a través de una coincidencia de patrones:
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 nada más. Por lo tanto, creará un Foo con cuatro parámetros (porque no puede mirar dentro sin que exista). El primero, ya que lo estamos probando, necesitamos evaluar todo el camino para4
que nos demos cuenta de que no coincide.
El segundo no necesita ser evaluado, porque no lo estamos probando. Por lo tanto, en lugar de 6
ser almacenado en esa ubicación de memoria, sólo tendremos que almacenar el código para una posible evaluación posterior, (3+3)
. Eso se convertirá en un 6 solo si alguien lo mira.
Sin embargo, el tercer parámetro tiene un !
frente, por lo que se evalúa estrictamente: (4+4)
se ejecuta y8
se almacena en esa ubicación de memoria.
El cuarto parámetro también se evalúa estrictamente. Pero aquí es donde se vuelve un poco complicado: estamos evaluando no completamente, sino solo con una forma de cabeza normal débil. Esto significa que descubrimos si es Nothing
o no Just
, y lo almacenamos, pero no vamos más allá. Eso significa que no almacenamos Just 10
pero en realidadJust (5+5)
, dejamos el thunk adentro sin evaluar. Es importante saberlo, 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 BangPatterns
extensión de idioma:
f x !y = x*y
f (1+1) (2+2)
devolverá el golpe (1+1)*4
.