Es una declaración de rigor. Básicamente, significa que debe evaluarse a lo que se denomina "forma débil de cabeza normal" 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 para ejecutar averiguar su valor . En ese momento, un Foo ni siquiera existe, solo el código.
Pero en algún momento alguien puede tratar de buscar en su interior, probablemente a través de una comparación de patrones:
case f of
Foo 0 _ _ _ -> "first arg is zero"
_ -> "first arge is something else"
Esto va a ejecutar código suficiente 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, tenemos que evaluar todo el camino hasta 4
, donde nos damos cuenta de que no coincide.
No es necesario evaluar el segundo, porque no lo estamos probando. Por lo tanto, en lugar de 6
almacenados en esa ubicación de memoria, almacenaremos 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 !
en frente de ella, por lo que está estrictamente evaluado: se ejecuta (4+4)
, 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 vuelve un poco complicado: estamos evaluando no completamente, pero solo a una forma de cabeza normal débil. Esto significa que averiguamos si es Nothing
o Just
algo, y lo almacenamos, pero no vamos más allá. Eso significa que no almacenamos Just 10
, sino realmente Just (5+5)
, dejando el thunk dentro sin evaluar. Esto es importante de saber, aunque creo que todas las implicaciones de esto van más allá del alcance de esta pregunta.
Puede anotar argumentos de la función de la misma manera, si se habilita la extensión BangPatterns
idioma:
f x !y = x*y
f (1+1) (2+2)
devolverá el golpe seco (1+1)*4
.
Sospecho que esta podría ser una pregunta muy común; Claramente recuerdo haberme preguntado exactamente lo mismo, hace mucho tiempo. –