Pourquoi ne sont-ils pas équivalents?
show $ if someCondition then someInt else some double
et
if someCondition then show someInt else show someDouble
Je comprends que si vous isolez la if ... else
partie dans le premier exemple d'une expression par elle-même, vous ne pouvez pas représenter son type avec un type de somme anonyme, le genre de Int | Double
, comme quelque chose que vous pourriez faire facilement dans TypeScript (en mentionnant TypeScript parce que c'est le langauge que j'utilisais souvent et qui prend en charge les types Sum), et devrait recourir à l'utilisation des Either
données basées sur ce qu'il appellerait show
.
L'exemple que j'ai donné ici est trivial mais pour moi, il est plus logique de penser "D'accord, nous allons montrer quelque chose, et que quelque chose dépend de someCondition
" plutôt que "D'accord si une certaine condition est vraie, puis affichez une pour moins de duplication de code (ici, le spectacle est répété deux fois, mais cela pourrait aussi être une application de fonction longue et au lieu d'un, if ... else
il pourrait y avoir> 2 branches à considérer)
Dans mon esprit, il devrait être facile pour le compilateur de vérifier si chacun des types qui font le type sum (ici Int | Double
) pourrait être utilisé comme paramètre pour show
fonctionner et décider si les types sont corrects ou non. Encore mieux, cette show
fonction retourne toujours quelque string
soit le type des paramètres, donc le compilateur n'a pas à transporter avec lui toutes les "branches" possibles (donc tous les types possibles).
Est-ce par choix qu'une telle fonctionnalité n'existe pas? Ou est-ce plus difficile à mettre en œuvre que je pense?
la source
if ... then ... else ...
, doit avoir le même type dans la partiethen
etelse
. Vous pouvez le voir comme un opérateur ternaire dans certains langages de programmation.making all conversions explicit
. Dans ma question, je ne veux pas que Haskell jette unInt
à unDouble
ou vice versa. Je viens d'utiliser ces deux types comme exemple. Vous pouvez remplacer chaqueInt
aveca
etDouble
avecb
dans ma question où les deux types dériventShow
. Je comprends qu'il n'y en a pasanonymous sum types
à Haskell, mais j'aimerais savoir pourquoi c'est le cas et ce qui nous empêche de concevoir le langage pour l'avoir.x :: Int | Bool
et nous devons compilershow x
, il n'y a pas de moyen facile de savoir quel pointeur vers la fonction utiliser pour appelershow
, dans un RTS basé sur l'effacement de type. Nous aurions probablement besoin de conserver certaines informations au niveau du type lors de l'exécution.(String, Int)
n'est pas anonyme. Il s'agit simplement d'un type de produit standard avec une syntaxe amusante.(String | Int)
serait très différent. Commencez par vous demander si elle(Int|Int)
devrait être identiqueInt
et pourquoi.Réponses:
Toutes les parties d'une expression doivent être bien typées. Le type de
if someCondition then someInt else someDouble
devrait être quelque chose commeexists a. Show a => a
, mais Haskell ne prend pas en charge ce type de quantification existentielle.Mise à jour: Comme le souligne chi dans un commentaire , cela serait également possible si Haskell avait un support pour les types union / intersection (qui ne sont pas les mêmes que les types sum / product), mais ce n'est malheureusement pas le cas.
la source
Int ∪ Double
, alors vous saurez que vous en avez un, mais vous ne pourrez pas faire de correspondance de motif pour voir lequel, donc vous ne pouvez faire que des choses valables pour les deux possibilités.typeof
opérateur qui peut compenser le manque de balisage et voir quel type est utilisé de toute façon. Haskell est entièrement effacé, donc s'il supportait cette fonctionnalité, il n'y aurait pas d'équivalent.Il existe des types de produits avec une syntaxe légère, écrits
(,)
, en Haskell. On pourrait penser qu'un type de somme avec une syntaxe légère, quelque chose comme(Int | String)
, serait une excellente idée. La réalité est plus compliquée. Voyons pourquoi (je prends quelques libertés avecNum
, elles ne sont pas importantes).Si cela doit renvoyer une valeur de type like
(Int | String)
, que doit renvoyer le suivant?(Int | Int)
évidemment, mais si cela est distinct de plaineInt
nous sommes en grande difficulté. Donc(Int | Int)
devrait être identique à plainInt
.On peut immédiatement voir que ce n'est pas seulement une syntaxe légère pour les types de somme, mais une toute nouvelle fonctionnalité de langage. Un autre type de système de saisie, si vous voulez. Devrions-nous en avoir un?
Regardons cette fonction.
Maintenant, quel type fait
mysteryType
-il? Évidemmentdroite? Et si
a
etb
sont du même type?Cela devrait être clair
Int
comme nous l'avons convenu précédemment. Maintenant,mysteryType
renvoyez parfois un type de somme anonyme, et parfois non, selon les arguments que vous passez. Comment feriez-vous pour correspondre à une telle expression? Que pouvez-vous en faire? Sauf des choses triviales comme "show" (ou quelles que soient les méthodes d'autres classes de types, ce serait une instance de), pas beaucoup. Sauf si vous ajoutez des informations de type d'exécution à la langue, c'est-à-dire qu'ellestypeof
sont disponibles - et que Haskell est une langue entièrement différente.Donc voilà. Pourquoi Haskell n'est-il pas un TypeScript? Parce que nous n'avons pas besoin d'un autre TypeScript. Si vous voulez TypeScript, vous savez où le trouver.
la source