Types de somme - Pourquoi dans Haskell est `show (Int | Double)` différent de `(show Int) | (afficher Double) `

9

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 ... elsepartie 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 Eitherdonné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 ... elseil 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 showfonctionner et décider si les types sont corrects ou non. Encore mieux, cette showfonction retourne toujours quelque stringsoit 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?

Mehdi Saffar
la source
2
Un if ... then ... else ..., doit avoir le même type dans la partie thenet else. Vous pouvez le voir comme un opérateur ternaire dans certains langages de programmation.
Willem Van Onsem
1
Je suis d'accord sur le making all conversions explicit. Dans ma question, je ne veux pas que Haskell jette un Intà un Doubleou vice versa. Je viens d'utiliser ces deux types comme exemple. Vous pouvez remplacer chaque Intavec aet Doubleavec bdans ma question où les deux types dérivent Show. Je comprends qu'il n'y en a pas anonymous 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.
Mehdi Saffar
4
Je pense que ces types sont appelés types d'union . Un type somme est essentiellement une variante balisée du type union, où chaque valeur doit porter une balise gauche / droite au-delà de la valeur du type interne. Je m'attends à ce que l'inférence de type avec les types d'union, avec toutes les fonctionnalités de niveau type de Haskell, soit très difficile à réaliser. Si x :: Int | Boolet nous devons compiler show x, il n'y a pas de moyen facile de savoir quel pointeur vers la fonction utiliser pour appeler show, 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.
chi
1
Ne pas avoir de types de somme anonymes est une décision de conception des concepteurs Haskell. Je ne sais pas trop quel genre d'avantages ils apporteraient à la table, mais je vois où ils compliqueraient les choses. Donc, je suppose qu'ils sont laissés de côté parce que le rapport coût / bénéfice n'est pas là. Mais pour être absolument sûr, vous devez demander aux concepteurs de la langue d'origine et / ou aux mainteneurs actuels. Je ne pense pas que cela poserait une grande question SO, car il y a beaucoup d'opinions et de goûts personnels impliqués dans la conception d'un langage.
n. «pronoms» m.
4
(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 identique Intet pourquoi.
n. «pronoms» m.

Réponses:

8

Toutes les parties d'une expression doivent être bien typées. Le type de if someCondition then someInt else someDoubledevrait être quelque chose comme exists 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.

Joseph Sible-Reinstate Monica
la source
Pourriez-vous expliquer la différence entre les types d'union / intersection et les types somme / produit? J'ai toujours pensé que c'était pareil, sauf pour l'anonymat?
Mehdi Saffar
1
@MehdiSaffar Anonymous comme dans non marqué, pas comme dans un constructeur sans nom. En d'autres termes, si vous en avez un 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.
Joseph Sible-Reinstate Monica
2
Pour plus de clarté, TypeScript a des informations de type disponibles au moment de l'exécution, donc il a un typeofopé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.
Joseph Sible-Reinstate Monica
7

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 avec Num, elles ne sont pas importantes).

if someCondition then 42 else "helloWorld"

Si cela doit renvoyer une valeur de type like (Int | String), que doit renvoyer le suivant?

if someCondition then 42 else 0

(Int | Int) évidemment, mais si cela est distinct de plaine Int nous sommes en grande difficulté. Donc (Int | Int)devrait être identique à plain Int.

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.

mysteryType x a b = if x then a else b

Maintenant, quel type fait mysteryType -il? Évidemment

mysteryType :: Bool -> a -> b -> (a|b)

droite? Et si aetb sont du même type?

let x = mysteryType True 42 0

Cela devrait être clair Intcomme nous l'avons convenu précédemment. Maintenant, mysteryTyperenvoyez 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'elles typeofsont 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.

n. «pronoms» m.
la source
1
@MichaWiedenmann Franchement, je ne sais pas si "pertinent" est le bon mot. Je pense que c'est utile d'une manière ou d'une autre. Oui, je me suis arrêté un instant et j'ai pensé à l'inclure. Mais je sais que je me trompe parfois.
n. «pronoms» m.
Pas de problème, c'est votre message, vous décidez.
Micha Wiedenmann
Alors, quels sont vos pronoms?
dfeuer