Quelle est la différence entre non définie dans Haskell et nulle en Java?
Question
Les deux sont des termes dont le type est l'intersection de tous les types (inhabitée). Les deux peuvent être transmis autour de code sans défaut jusqu'à ce que l'on tente de les évaluer. La seule différence que je vois est que Java, il y a une échappatoire qui permet null
à évaluer exactement une seule opération, qui consiste à comparer l'égalité de référence (==
) - alors que dans Haskell undefined
ne peut pas être évalué à tout cela sans jeter un exception. Est-ce la seule différence?
Modifier
Ce que je veux vraiment essayer d'obtenir à cette question est, pourquoi y compris null
en Java une telle décision apparemment pauvre, et comment Haskell y échapper? Il me semble que le vrai problème est que vous pouvez faire quelque chose utile avec null
, à savoir que vous pouvez le vérifier pour état NULL . Parce que vous êtes autorisé à le faire, il est devenu convention standard pour passer autour des valeurs nulles dans le code et de les indiquer « aucun résultat » au lieu de « il y a une erreur logique dans ce programme ». Alors que dans Haskell, il n'y a aucun moyen de vérifier si un evalue terme en bas sans l'évaluer et le programme d'exploser, il ne pourrait jamais être utilisé de telle manière à indiquer « aucun résultat ». Au lieu de cela, on est obligé d'utiliser quelque chose comme Maybe
.
Désolé s'il semble que je joue rapide et lâche avec le terme « évaluer » ... Je suis en train de faire une analogie ici et avoir du mal à phrasé précisément. Je suppose que c'est un signe que l'analogie est imprécise.
La solution
Quelle est la différence entre non définie dans Haskell et nulle en Java?
Ok, revenons en arrière un peu.
« non défini » dans Haskell est un exemple d'une valeur « bas » (notée ?). Une telle valeur représente l'un quelconque état indéfini, collé ou partiel dans le programme.
De nombreuses formes de fond existent: les boucles non terminales, des exceptions, des échecs de correspondance de motif - en fait tout état dans le programme qui est indéfini dans un certain sens. La valeur undefined :: a
est un exemple canonique d'une valeur qui met le programme dans un état non défini.
undefined
lui-même est pas particulièrement spéciale - sa non câblée dans - et vous pouvez mettre en œuvre la undefined
de Haskell en utilisant une expression à rendement bas. Par exemple. c'est une implémentation valide de undefined
:
> undefined = undefined
Ou sortir immédiatement (l'ancien compilateur Gofer utilisé cette définition):
> undefined | False = undefined
La propriété principale de fond est que si une expression évalue à fond, ensemble de votre programme évaluera en bas:. Le programme est dans un état indéfini
Pourquoi voudriez-vous la valeur d'un tel? Eh bien, dans une langue paresseuse, vous pouvez souvent manipuler des structures ou des fonctions qui stockent des valeurs inférieures, sans le programme étant en bas lui-même.
par exemple. une liste de boucles infinies est parfaitement cromulent:
> let xs = [ let f = f in f
, let g n = g (n+1) in g 0
]
> :t xs
xs :: [t]
> length xs
2
Je ne peux pas faire grand-chose avec les éléments de la liste:
> head xs
^CInterrupted.
Cette manipulation de choses infinies fait partie des raisons pour lesquelles si amusant de Haskell et expressif. Un résultat de la paresse est Haskell porte une attention particulière aux valeurs bottom
.
Cependant, clairement, le concept de fond applique aussi bien à Java, ou toute autre langue (non totale). En Java, il existe de nombreuses expressions que les valeurs « de fond » de rendement:
- comparer une référence par rapport à zéro (bien que la note, ne se
null
, qui est bien définie);
division - par zéro;
- hors des limites du terrain exceptions;
- une boucle infinie, etc.
Vous n'ont tout simplement pas la possibilité de substituer un fond à un autre très facilement, et le compilateur Java ne fait pas beaucoup de choses à raisonner sur des valeurs inférieures. Cependant, ces valeurs sont là.
En résumé,
- déréférencement une valeur de
null
en Java est une expression spécifique qui donne une valeur inférieure à Java; - la valeur
undefined
dans Haskell est une expression générique bas rendement qui peut être utilisé n'importe où une valeur inférieure est nécessaire dans Haskell.
Voilà comment ils sont similaires.
Postscript
Quant à la question de null
elle-même: pourquoi il est considéré comme une mauvaise forme
- Tout d'abord, la
null
Java est essentiellement équivalente à en ajoutant unMaybe a
implicite à chaquea
de type dans Haskell . - déréférencement
null
équivaut à la correspondance de motif pour que le cas deJust
:f (Just a) = ... a ...
Ainsi, lorsque la valeur passée est Nothing
(en Haskell), ou null
(en Java), votre programme atteint un état non défini. Ceci est mauvais. Votre programme se bloque
Alors, en ajoutant null
tous type, vous avez juste fait beaucoup plus facile de créer des valeurs de bottom
par accident - les types ne vous aide. Votre langue est plus vous aider à éviter ce genre d'erreur particulier, et qui est mauvais.
Bien sûr, d'autres valeurs de fond sont toujours là: les exceptions (comme undefined
), ou des boucles infinies. Ajout d'un nouveau mode de défaillance possible de toutes les fonctions - déréférencement null
- juste le rend plus facile à écrire des programmes qui plantent
Autres conseils
Votre description n'est pas tout à fait correct. Vous dites null
ne peut pas être évalué. Cependant, depuis Java est une langue avide, cela signifierait que f(null)
jetterait un NPE, peu importe ce que la définition de f
est (parce que les arguments de méthode sont toujours évalués avant l'exécution de la méthode).
La seule raison pour laquelle vous pouvez passer autour undefined
dans haskell sans obtenir une exception est que haskell est paresseux et n'évalue pas d'arguments à moins que nécessaire.
Une autre différence entre indéfini et nulle est que undefined
est une valeur simple, définie dans la bibliothèque standard. Si elle n'a pas été défini dans la bibliothèque standard, vous pouvez définir vous-même (en écrivant myUndefined = error "My Undefined
par exemple).
En Java null
est un mot-clé. S'il n'y avait pas de mot-clé null
, vous ne seriez pas en mesure de définir (faire l'équivalent de la définition de haskell, à savoir Object myNull = throw(new Exception())
, ne travaillerait parce que l'expression serait évaluée là).