2016-11-19 5 views
1

En this, les unions non étiquetées sont décrites comme une forme de sous-typage.Autorise les unions non étiquetées équivalentes à autoriser les classes de types?

Les classes de types sont également une forme de sous-typage.

Sont-ils conceptuellement équivalents? Ils sont, comment pourrais-je les implémenter chez Haskell?

+4

Je dirais que Haskell n'a pas de sous-typage comme il serait traditionnellement défini car chaque valeur a exactement le type _one_. Typeclasses sont simplement un moyen d'étendre le langage des types pour permettre le polymorphisme défini par l'utilisateur. C'est-à-dire, il laisse une valeur 'x' avoir un type' C a => a' où 'C' est un ensemble de règles' a' qui doit être conforme; mais toujours 'x' a exactement un type. Comparez ceci avec le sous-typage OOPy où une valeur 'x' a plusieurs types: son type de base, et tout type qui subclasse du type de base. – hao

+1

Un autre argument plus pédant: le sous-typage inhiberait l'inférence de type principal de type DHM que possèdent les compilateurs Haskell, contrairement aux typeclasses. – hao

+3

Pour approfondir le point de @ haoformayor: ne pas confondre le sous-typage et le polymorphisme ad-hoc. Le sous-typage est une caractéristique du polymorphisme ad-hoc, et les classes de types sont plutôt différentes. –

Répondre

4

Les classes de types sont également une forme de sous-typage.

Ils ne le sont pas. Par souci d'illustration, nous allons revenir à la TypeScript examples je faisais allusion dans cette question:

Si nous avons une valeur qui a un type d'union, nous ne pouvons membres d'accès qui sont communs à tous les types dans l'Union .

interface Bird { 
    fly(); 
    layEggs(); 
} 

interface Fish { 
    swim(); 
    layEggs(); 
} 

function getSmallPet(): Fish | Bird { 
    // ... 
} 

let pet = getSmallPet(); 
pet.layEggs(); // okay 
pet.swim(); // errors 

Ici, le type de retour de getSmallPet est ni Fish ni Bird, mais un supertype des deux qui a comme membres les membres communs aux deux Fish et Bird. Un Fish est également un Fish | Bird, et il en est ainsi un Bird.

Que se passe avec des classes de type est tout à fait différent:

foo :: Num a => a -> a 
foo x = (x * x) + x 

Bien que les deux foo (3 :: Integer) et foo (7.7 :: Double) travail, cela ne signifie pas qu'il y ait un supertype correspondant à Num que (3 :: Integer) et (7.7 :: Double) aussi ont. Plutôt, tout ce que Num a => a -> a dit est que votre choix de a devrait avoir une instance de Num (et il est intéressant de souligner que Num n'est pas un type), de sorte qu'il existe des implémentations appropriées de (*) et (+) pour votre type choisi. Contrairement aux méthodes OOP, (*) et (+) n'appartiennent à aucun type particulier, et il n'est donc pas nécessaire d'introduire un supertype afin de les utiliser avec Integer et Double.

+0

Cette réponse aide beaucoup, merci. Néanmoins, j'ai le sentiment que les deux concepts sont au moins liés, car l'exemple 'Pet' peut aussi être implémenté via des classes de types. Dit comme une question: "Les contraintes de classe de type sont-elles aussi puissantes que les unions non étiquetées?" (Bien que ce soit probablement plus approprié comme question de suivi). – ThreeFx

+3

@ThreeFx Nous pourrions dire que, dans ce cas, ils seraient deux façons très différentes d'atteindre le même objectif.A ce propos, il convient de noter que l'aspect non marqué n'est pas essentiel à la discussion - si nous avions, dans l'exemple TypeScript, une interface 'Oviparous 'avec une méthode' layEggs' que 'Fish' et' Bird' étendraient , la différence fondamentale resterait la même. Une question pertinente, quoique quelque peu tangentielle: [* Polymorphisme paramétrique vs polymorphisme ad-hoc *] (http://stackoverflow.com/q/6730126/2751851). – duplode