Qu'est-ce que la Faiblesse de la Tête Forme Normale?
Ce n' la Faiblesse de la Tête à la Forme Normale de (WHNF) signifie? Ce n' Tête à la forme Normale de (HNF) et Forme Normale (NF) signifie?
Real World Haskell états:
Le familier seq fonction évalue une expression de ce que nous appelons la tête
forme normale (en abrégé HNF). Il s'arrête une fois qu'il atteint la limite extérieure de
constructeur (la “tête”). Elle est distincte de la forme normale (NF), dans
dont une expression est complètement évaluées.Vous entendrez aussi Haskell programmeurs reportez-vous à la faiblesse de la forme normale de tête
(WHNF). Pour les données normales, la faiblesse de la tête à la forme normale est la même que la tête
forme normale. La différence se pose uniquement pour les fonctions, et il est trop
abscons pour qui nous intéresse ici.
J'ai lu un peu de ressources et définitions (Haskell Wiki et Haskell Liste De Courrier et Gratuit Dictionnaire) mais je ne l'obtenez pas. Quelqu'un peut peut-être donner un exemple ou fournir un profane définition?
Je suis deviner qu'il serait semblable à:
WHNF = thunk : thunk
HNF = 0 : thunk
NF = 0 : 1 : 2 : 3 : []
Comment seq
et ($!)
se rapportent à WHNF et HNF?
Mise à jour
Je suis encore confus. Je sais que certaines des réponses que dire de l'ignorer HNF. À partir de la lecture des différentes définitions, il semble qu'il n'y a pas de différence entre les données dans WHNF et HNF. Cependant, il semble comme il y a une différence quand il s'agit d'une fonction. Si il n'y a pas de différence, pourquoi est - seq
nécessaire pour foldl'
?
Un autre point de confusion est à partir de la Haskell Wiki, qui stipule que seq
réduit à WHNF, et ne rien faire pour l'exemple suivant. Alors ils disent qu'ils ont à utiliser seq
forcer l'évaluation. N'est-ce pas la forcer à HNF?
Commune newbie de la pile déborde code:
myAverage = uncurry (/) . foldl' (\(acc, len) x -> (acc+x, len+1)) (0,0)
Des gens qui comprennent seq et la faiblesse de la tête forme normale (whnf) peut
de comprendre immédiatement ce qui ne va pas ici. (acc+x, len+1) est déjà
dans whnf, donc seq, ce qui réduit d'une valeur de whnf, ne fait rien pour cela.
Ce code va créer des thunks tout comme l'original foldl exemple,
il va juste être à l'intérieur d'un tuple. La solution est simplement de la force de la
les composants de la n-uplet, par exemplemyAverage = uncurry (/) . foldl' (\(acc, len) x -> acc `seq` len `seq` (acc+x, len+1)) (0,0)
-Haskell Wiki sur Stackoverflow
- Généralement on parle de WHNF et FRR. (FRR être ce que vous appelez NF)
- Quel est le R dans FRR stand for?
- Réduit
Vous devez vous connecter pour publier un commentaire.
Je vais essayer de donner une explication en termes simples. Comme d'autres l'ont souligné, la tête forme normale ne s'applique pas à Haskell, je ne vais pas examiner ici.
Forme normale
Une expression de la forme normale est pleinement évalués, et pas de sous-expression pourrait être évaluées plus en détail (c'est à dire qu'il ne contient aucune des nations unies-évalué thunks).
Ces expressions sont toutes de la forme normale:
Ces expressions ne sont pas en forme normale:
La faiblesse de la tête à la forme normale de
Une expression de la faiblesse de la tête à la forme normale a été évalué à l'ultrapériphériques données constructeur ou lambda abstraction (la tête). Les sous-expressions peut ou peut ne pas avoir été évalué. Par conséquent, chaque forme normale d'expression est aussi dans la faiblesse de la tête à la forme normale, bien que l'inverse ne tient pas en général.
Pour déterminer si une expression est dans la faiblesse de la tête à la forme normale, nous n'avons qu'à regarder la partie la plus extérieure de l'expression. Si c'est une des données du constructeur ou d'un lambda, c'est dans la faiblesse de la tête à la forme normale. Si c'est une fonction de l'application, il n'est pas.
Ces expressions sont dans la faiblesse de la tête forme normale:
Comme mentionné précédemment, toutes de la forme normale des expressions ci-dessus sont aussi dans la faiblesse de la tête à la forme normale.
Ces expressions ne sont pas dans la faiblesse de la tête forme normale:
Débordements de pile
L'évaluation d'une expression à la faiblesse de la tête forme normale peut exiger que d'autres expressions être évalué à WHNF premier. Par exemple, pour évaluer
1 + (2 + 3)
à WHNF, nous devons d'abord évaluer2 + 3
. Si l'évaluation d'une expression unique conduit à un trop grand nombre de ces imbriqués les évaluations, le résultat est un débordement de pile.Ce qui se passe quand vous construire une grande expression qui ne produisent pas de toutes les données constructeurs ou des lambdas jusqu'à ce qu'une grande partie de cela a été évaluée. Ce sont souvent causés par ce genre d'utilisation de
foldl
:Remarquez comment il doit aller assez profond avant de pouvoir obtenir l'expression dans la faiblesse de la tête à la forme normale.
Vous pouvez vous demander, pourquoi ne pas Haskell réduire l'intérieur des expressions à l'avance? C'est à cause de Haskell paresse. Puisqu'il ne peut être supposé que, en général, chaque sous-expression sera nécessaire, les expressions sont évaluées à partir de l'extérieur.
(GHC a une rigueur de l'analyseur qui permet de détecter certaines situations où une sous-expression est toujours nécessaire, et il peut alors évaluer à l'avance. Ce n'est qu'une optimisation, cependant, et vous ne devriez pas compter sur elle pour vous sauver de débordements).
Ce genre d'expression, d'autre part, est tout à fait sûr:
Pour éviter la construction de ces expressions de grande taille quand on sait toutes les sous-expressions devront être évalués, nous voulons forcer les parties intérieures être évalué à l'avance.
seq
seq
est une fonction spéciale qui est utilisée pour forcer les expressions à évaluer. Sa sémantique est queseq x y
signifie que chaque fois quey
est évaluée à la faiblesse de la tête à la forme normale,x
est également évaluée à la faiblesse de la tête à la forme normale.Il est entre autres utilisé dans la définition de
foldl'
, la stricte variante defoldl
.Chaque itération de
foldl'
les forces de l'accumulateur à WHNF. Il permet donc d'éviter la constitution d'une importante expression, et il permet donc d'éviter les débordement de la pile.Mais comme l'exemple sur HaskellWiki mentionne, il ne vous fait pas gagner dans tous les cas, que l'accumulateur est seulement évaluée à WHNF. Dans l'exemple, l'accumulateur est un n-uplet, donc il ne force l'évaluation de la n-uplet constructeur, et pas
acc
oulen
.Pour éviter cela, nous devons faire en sorte que l'évaluation de la n-uplet constructeur forces de l'évaluation de
acc
etlen
. Nous faisons cela en utilisantseq
.\x -> 1 + 1
est WHNF mais pas HNF.seq
leurs arguments?foldl
avant de pouvoir faire les sommes, générant beaucoup d'inutiles thunks dans le processus.foldl'
avec le n-uplet, pourriez-vous éventuellement utiliser deepSeq à l'intérieur defoldl'
qui englobera laseq
utilisation à l'intérieurf
?deepseq
serait aussi travailler.data List = Cons a (List a) | Nil
. Avez-vous oublié le paramètre de type ici -data List a = ...
?foldl'
avecf (acc, len) x = (acc + x, len +1)
) il me donne (6,3) directement, sans l'aide deseq
. Comment venir?:set +s
. Vous pouvez alors voir quefoldl' f
finit allouer plus de thunks quefoldl' f'
.La section sur les Thunks et la Faiblesse de la Forme Normale de Tête dans le Haskell Wikibooks description de la paresse donne une très bonne description de WHNF avec ce utile de représentation:
Haskell programmes sont expressions et ils sont gérés par l'exécution évaluation.
Pour évaluer une expression, remplacer toutes les applications de fonctions par leurs définitions. L'ordre dans lequel vous faites cela n'importe pas beaucoup, mais il est toujours important: commencez avec la plus externe de l'application et de procéder de gauche à droite; cela s'appelle évaluation différée.
Exemple:
L'évaluation s'arrête lorsqu'il n'y a plus de fonction des applications de gauche à remplacer. Le résultat est dans forme normale (ou réduit à la forme normale de, FRR). Peu importe l'ordre dans lequel vous évaluer une expression, vous vous retrouvez toujours avec la même forme normale (mais seulement si l'évaluation se termine).
Est légèrement différente de la description de l'évaluation différée. À savoir, il est dit que vous devez évaluer tout à la faiblesse de la tête à la forme normale de seulement. Il y a précisément trois cas pour une expression dans WHNF:
constructor expression_1 expression_2 ...
(+) 2
ousqrt
\x -> expression
En d'autres termes, le chef de l'expression (c'est à dire de l'extérieur de la fonction de demande) ne peut pas être évaluées plus en détail, mais l'argument de fonction peut contenir des expressions non évaluées.
Exemples de WHNF:
Notes
seq
dansfoldl'
forcer l'évaluation de WHNF à HNF?seq expr1 expr2
évaluera la première expressionexpr1
à WHNF avant l'évaluation de la deuxième expressionexpr2
.Une bonne explication avec des exemples est donné à http://foldoc.org/Weak+Tête+Normal+Formulaire Tête forme normale simplifie encore les bits d'une expression à l'intérieur d'une fonction d'abstraction, tandis que les "faibles" de la tête à la forme normale s'arrête à la fonction des abstractions.
À partir de la source, si vous avez:
qui est dans la faiblesse de la tête à la forme normale, mais pas la tête en forme normale... parce que l'application possible est coincé à l'intérieur d'une fonction qui ne peut pas encore été évalué.
Réelle de la tête forme normale serait difficile à mettre en œuvre efficacement. Il aurait besoin de fouiller à l'intérieur des fonctions. Donc l'avantage de la faiblesse de la tête à la forme normale est que vous pouvez toujours mettre en œuvre des fonctions comme un type opaque, et par conséquent, il est de plus compatible avec les langages compilés et d'optimisation.
La WHNF ne voulez pas que le corps de la lambda pour être évaluées,
seq
veut que son premier argument en WHNF, doncévalue à
au lieu de, ce serait en utilisant HNF
Fondamentalement, supposons que vous avez une sorte de thunk,
t
.Maintenant, si l'on veut évaluer
t
à WHNF ou NHF, qui sont les mêmes, sauf pour les fonctions, nous constatons que nous obtenons quelque chose commet1 : t2
oùt1
ett2
sont thunks. Dans ce cas,t1
serait votre0
(ou plutôt, un thunk à0
donné aucun extra unboxing)seq
et$!
evalute WHNF. Notez que