4 Réponses :


3
votes

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);


0 commentaires

3
votes

Par souci de cette question, disons qu'il y a trois choses qui peuvent forcer une valeur à être évaluée:

  • Motif correspondant à cette valeur li>
  • Application de la valeur à un argument li>
  • en l'utilisant comme premier argument de 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
    


0 commentaires

9
votes

La fonction spéciale SEQ é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 :

Une expression est en forme de tête faible (WHNF) si elle est soit:

  • Un constructeur (éventuellement appliqué aux arguments) comme true, juste (Square 42) ou (:) 1
  • une fonction appliquée à trop peu d'arguments (peut-être aucun) comme (+) 2 ou SQRT.
  • ou une abstraction lambda \ x -> expression.

    Un point important est que lorsqu'une expression est un constructeur, SEQ ne regarde que la balise du constructeur. Ainsi, SEQ (juste indéfini) 1 évalue vers 1 .

    Un autre point important est que tous les types de haskell sont levé - 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 ou non défini ). Après avoir évalué SEQ A B , nous pouvons être sûrs que l'évaluation A sur WHNF ne conduise pas à une boucle infinie ou à une exception.

    armé de cette connaissance, regardons votre exemple: xxx

    lorsque SEQ UNDEF1 () est évalué, SEQ essaie d'abord de savoir laquelle des trois catégories ci-dessus UNDEF1 appartient à. Mais undef1 est non défini , et donc l'ensemble de l'expression est donc d'évaluer à non défini .

    Cependant, dans le cas du SEQ UNDEF2 () = () , le premier argument est une abstraction Lambda. Étant donné que SEQ ne peut pas voir le passé de la Lambda, il renvoie le deuxième argument.

    Le troisième exemple, UNDEF2 () = non défini est juste un Résultat simple de l'évaluation de l'application (\ _ -> non défini) () .


0 commentaires

3
votes

Eh bien, juste pour écrire une réponse Bridifer que les autres: afin de forcer l'évaluation d'une expression comme FX , Haskell a d'abord besoin de savoir quelle fonction f est, Puis appliquez-le x . En plus de termes techniques, chaque fois que fx est forcé , f doit être forcé.

revenons à vos définitions maintenant: xxx

forçage UNDEF1 et UNDEF2 produit des résultats différents. Forçage UNDEF11 produit non défini immédiatement, tandis que forcer UNDEF2 produit un Thunk qui, lorsqu'il est appliqué à un argument, produit non défini .

Je suppose que vous êtes mal compris que SEQ fait; J'ai l'impression que vous pensez SEQ Undef2 () est censé appliquer UNDEF2 à () , mais ça ne fait pas ça. Ce que SEQ :: A -> B -> B est de forcer son premier argument et de renvoyer le second. La différence entre SEQ Undef1 () et SEQ UNDEF2 () est simplement que seule la seconde réussit à forcer son premier argument, mais il renvoie simplement () .

Si je suis juste à propos de votre intention avec le code ci-dessus, ce que vous cherchez est ($!) :: (A -> b) -> A -> B , qui applique son premier argument au second et oblige le résultat. Donc, ces deux échecent avec non défini : xxx


1 commentaires

Hehe, oui. Je dois avouer. Je n'étais pas entièrement clair sur SEQ. Merci.