Je suis tombé sur la définition suivante en essayant d'apprendre Haskell en utilisant un vrai projet pour le piloter. Je ne comprends pas ce que signifie le point d'exclamation devant chaque argument et mes livres ne semblent pas le mentionner.
data MidiMessage = MidiMessage !Int !MidiMessage
Réponses:
C'est une déclaration de rigueur. Fondamentalement, cela signifie qu'il doit être évalué selon ce que l'on appelle la "forme normale de tête faible" lorsque la valeur de la structure de données est créée. Regardons un exemple, pour voir ce que cela signifie:
La fonction
f
ci-dessus, une fois évaluée, renverra un "thunk": c'est-à-dire le code à exécuter pour déterminer sa valeur. À ce stade, un Foo n'existe même pas encore, juste le code.Mais à un moment donné, quelqu'un peut essayer de regarder à l'intérieur, probablement à travers une correspondance de modèle:
Cela va exécuter suffisamment de code pour faire ce dont il a besoin, et pas plus. Il créera donc un Foo avec quatre paramètres (car vous ne pouvez pas regarder à l'intérieur sans qu'il existe). Le premier, puisque nous le testons, nous devons évaluer tout le chemin vers
4
, où nous réalisons qu'il ne correspond pas.La seconde n'a pas besoin d'être évaluée, car nous ne la testons pas. Ainsi, plutôt que d'
6
être stockés dans cet emplacement mémoire, nous allons stocker le code d'évaluation possible plus tard,(3+3)
. Cela ne deviendra un 6 que si quelqu'un le regarde.Le troisième paramètre, cependant, a un
!
devant, il est donc strictement évalué:(4+4)
est exécuté et8
est stocké dans cet emplacement de mémoire.Le quatrième paramètre est également strictement évalué. Mais voici où cela devient un peu délicat: nous évaluons pas complètement, mais seulement pour une forme de tête normale faible. Cela signifie que nous déterminons si c'est
Nothing
ouJust
quelque chose, et stockons cela, mais nous n'allons pas plus loin. Cela signifie que nous ne stockons pas,Just 10
mais en faitJust (5+5)
, laissant le thunk à l'intérieur sans évaluation. Il est important de le savoir, bien que je pense que toutes les implications de cela dépassent la portée de cette question.Vous pouvez annoter des arguments de fonction de la même manière, si vous activez l'
BangPatterns
extension de langage:f (1+1) (2+2)
retournera le thunk(1+1)*4
.la source
seq
.Un moyen simple de voir la différence entre les arguments de constructeur stricts et non stricts est de savoir comment ils se comportent lorsqu'ils ne sont pas définis. Donné
Puisque l'argument non strict n'est pas évalué par
second
, la transmissionundefined
ne pose pas de problème:Mais l'argument strict ne peut pas l'être
undefined
, même si nous n'utilisons pas la valeur:la source
!
symbole a, plutôt que de plonger dans les détails de l'implémentation interne.Je pense que c'est une annotation de rigueur.
Haskell est un langage fonctionnel pur et paresseux , mais parfois les frais généraux de la paresse peuvent être trop ou gaspiller. Donc, pour faire face à cela, vous pouvez demander au compilateur d'évaluer pleinement les arguments d'une fonction au lieu d'analyser les thunks.
Il y a plus d'informations sur cette page: Performance / Strictness .
la source
map Just [1,2,3]
pour obtenir [Juste 1, Juste 2, Juste 3]) et ainsi de suite. Je trouve utile de penser à la capacité de faire correspondre les modèles avec eux ainsi qu'à une installation complètement indépendante.