4 Réponses :
Ils ne sont pas la même chose. UNDEF1 est une fonction de A à B, mais quelle fonction est indéfinie. L'évaluation de l'UNDEF1 à la forme de tête normale vous donne indéfini.
UNDEF2 est une fonction de A à b. Plus précisément, c'est une fonction qui ignore son argument et renvoie indéfini. Mais undef2 n'est pas non défini lui-même. Seulement lorsque vous essayez d'évaluer la fonction (comme dans votre troisième ligne), vous n'êtes pas non défini. Ainsi, lorsque vous évaluez l'UNDF2 à la forme normale de la tête, vous obtenez une fonction appropriée, non indéfini. P>
Pour le mettre en termes plus impératifs (toujours une source d'inexactitude, mais si vous êtes plus familier avec cela, mais si vous êtes plus familier avec cela. Il illustre le point joliment), pensez à UNDEF1 en tant que propriété Getter qui ne revient jamais. (À Haskell, ne pas retourner et non défini sont sémantiquement équivalents.) Undef2 est un getteur de propriété qui retourne une fonction; C'est cette fonction qui ne reviendra pas si vous l'appelez. En C #: P>
var x = Undef1; var y = Undef2; var z = Undef2(null);
Par souci de cette question, disons qu'il y a trois choses qui peuvent forcer une valeur à être évaluée:
SEQ code> li>
ul> La situation réelle est légèrement plus compliquée, mais pas d'une manière qui compte ici. P>
En outre, ce forçage ne se produit que dans le contexte de l'expression extérieure, donc plutôt que de penser à Celles-ci comme "forçage d'une évaluation" de manière abstraite, il est utile de penser à eux comme étant l'évaluation de l'expression externe dépend de l'évaluation de cette valeur. C'est pourquoi, par exemple, SEQ X X code> ne force pas x code> en aucun sens, car c'est la valeur finale de l'expression de toute façon; Il est indiqué que lorsque l'expression extérieure (dont la valeur est x code>) est évaluée, il devrait également évaluer x code>, qui est redondant. p> Enfin, tout La valeur qui dépend de forcer une valeur non définie est elle-même indéfinie. p>
passer à travers chaque expression: p> xxx pré> Dans ce cas Undef1 est indéfini et SEQ UNDEF1 x code> est une expression dont la valeur est x code> et dépend de l'évaluation UNDEF1 code>. Donc, l'expression dans son ensemble est indéfinie aussi, peu importe ce que le deuxième argument à SEQ code> est. P> xxx pré> Dans ce cas, Undef2 code> est pas em> non défini, mais le résultat de l'appliquer est. SEQ UNDEF2 X CODE> est une expression dont la valeur est x code> et dépend de l'évaluation UNDEF2 code>. Cela ne provoque aucun problème et le premier argument à SEQ code> est rejeté, la valeur de l'expression est donc () code> ici. P> undef1 () = undefined
La fonction spéciale Une expression est en forme de tête faible (WHNF) si elle est soit: p>
Un point important est que lorsqu'une expression est un constructeur, Un autre point important est que tous les types de haskell sont levé em> - c'est-à-dire d'évaluer une valeur du type peut conduire à une boucle infinie exécutée ou une exception étant levée (généralement avec erreur code> ou armé de cette connaissance, regardons votre exemple: p> lorsque Cependant, dans le cas du Le troisième exemple, SEQ code> évalue son premier argument à une forme de tête faible et renvoie ensuite son deuxième argument. Une bonne explication de WHNF peut être trouvée ici , mais aux fins de cette réponse, je vais simplement utiliser le Définition Wiki Haskell :
SEQ code> ne regarde que la balise du constructeur. Ainsi, SEQ (juste indéfini) 1 code> évalue vers 1 code>. p> non défini code>). Après avoir évalué SEQ A B CODE>, nous pouvons être sûrs que l'évaluation A code> sur WHNF ne conduise pas à une boucle infinie ou à une exception. p> SEQ UNDEF1 () code> est évalué, SEQ CODE> essaie d'abord de savoir laquelle des trois catégories ci-dessus UNDEF1 code> appartient à. Mais undef1 code> est non défini code>, et donc l'ensemble de l'expression est donc d'évaluer à non défini code>. P> SEQ UNDEF2 () = () code>, le premier argument est une abstraction Lambda. Étant donné que SEQ code> ne peut pas voir le passé de la Lambda, il renvoie le deuxième argument. P> UNDEF2 () = non défini code> est juste un Résultat simple de l'évaluation de l'application (\ _ -> non défini) () code>. p> p>
Eh bien, juste pour écrire une réponse Bridifer que les autres: afin de forcer l'évaluation d'une expression comme revenons à vos définitions maintenant: p > forçage Je suppose que vous êtes mal compris que Si je suis juste à propos de votre intention avec le code ci-dessus, ce que vous cherchez est FX code>, Haskell a d'abord besoin de savoir quelle fonction f code> est, Puis appliquez-le x code>. En plus de termes techniques, chaque fois que fx code> est forcé em>, f code> doit être forcé. UNDEF1 code> et UNDEF2 code> produit des résultats différents. Forçage UNDEF11 code> produit non défini code> immédiatement, tandis que forcer UNDEF2 code> produit un Thunk qui, lorsqu'il est appliqué à un argument, produit non défini code >. p> SEQ code> fait; J'ai l'impression que vous pensez SEQ Undef2 () code> est censé appliquer UNDEF2 code> à () code>, mais ça ne fait pas ça. Ce que SEQ :: A -> B -> B code> est de forcer son premier argument et de renvoyer le second. La différence entre SEQ Undef1 () code> et SEQ UNDEF2 () code> est simplement que seule la seconde réussit à forcer son premier argument, mais il renvoie simplement () code>. p> ($!) :: (A -> b) -> A -> B code>, qui applique son premier argument au second et oblige le résultat. Donc, ces deux échecent avec non défini code>: p>
Hehe, oui. Je dois avouer. Je n'étais pas entièrement clair sur SEQ. Merci.