Par curiosité, existe-t-il des langages qui vous permettent de définir l'arithmétique sur les types pour en créer de nouveaux? Quelque chose comme:
interface A {
void a();
void b();
}
interface B {
void b();
void c();
}
interface C = A & B; // has b()
interface D = A | B; // has a(), b() and c()
interface E = (A & B) ^ B; // has c()
Je sais que dans certaines langues, ces idées peuvent être exprimées (c'est-à-dire que Java a List<Comparable & Serializable>
pour l'union des interfaces) mais je n'ai jamais entendu parler d'un langage qui prend en charge le type arithmétique. Merci!
programming-languages
type-systems
Haldean Brown
la source
la source
CanWriteAndCompare extends Serializable, Comparable {}
) et je réfléchissais à la façon de généraliser cela.A
ou unB
, avec deux implémentations qui se ressemblent exactement. Dans la méthode, j'appelle une méthode polymorphe qui peut prendre unA
ou unB
, donc les implémentations sont les mêmes, mais comme je dois prendre deux types distincts, j'ai besoin de deux implémentations. Ce serait plus facile si je pouvais le fairemyMethod(A | B aOrB)
.Or
opération peut être émulée par héritage multiple.Réponses:
Tangent ( 0.3 spec ) utilise quelque chose de similaire à cela. (Avertissement: ceci est mon propre petit projet de recherche)
Agit actuellement
with
comme un opérateur d'union modélisant l'héritage, bien que le pragmatisme l'ait rendu non commutatif. Une fois que vous introduisez des implémentations de méthodes, une union stricte de méthodes avec le même nom n'est souvent pas ce que vous voulez et impossible de faire de toute façon.intersect
est pris en charge que les modèles saisissent l'inférence pour quelque chose commefoo(T,T)
lorsque les paramètres sont différents.Les compléments étaient intéressants, mais ont conduit à des types partiels qui ne semblaient pas si utiles et / ou gênants à inclure correctement - ne sont donc pas inclus.
Je sais qu'il y a quelques autres langages de recherche que j'ai rencontrés qui avaient quelque chose de similaire, mais je ne m'en souviens pas pour le moment. Le problème principal est que les choses ne sont pas vraiment utiles sans typage structurel, ce qui n'est pas très populaire en soi. L'autre est que vous avez besoin d'une sorte de type (type de types) pour stocker le type construit, ou bien c'est juste un raccourci pour quelque chose qui n'est pas particulièrement idiomatique sans cette capacité. Et c'est beaucoup moins courant que le typage même structurel.
C'est biaisé, et ce n'est pas grand-chose, mais ça y est.
la source
Oui, Ceylan est une langue avec des types d'union et d'intersection ad hoc, comme décrit dans ce chapitre de la tournée de Ceylan:
C'est incroyable le nombre d'idiomes cool que vous en retirez. Voici un exemple intéressant que j'ai blogué récemment . Et voici une courte présentation où je passe rapidement en revue plusieurs idiomes simples .
Encore mieux, les types d'union / intersection sont le "chaînon manquant" qui fait que l'inférence d'argument de type générique fonctionne vraiment bien à Ceylan, contrairement à d'autres langages qui combinent le sous-type et le polymorphisme paramétrique.
Notez qu'il existe des limitations à ce type de "type arithmétique", comme vous l'avez décrit. Par exemple, vous ne pouvez pas avoir d'opérateur set complément au niveau du type, du moins pas sans introduire l'indécidabilité.
HTH
la source
Scala le prend en charge partiellement (intersections mais pas les unions), et tout langage avec sous-typage structurel (je pense que OCaml est un exemple) ou un système de type assez puissant pour émuler cela (Haskell est un classique) aura des "types-as-sets" complets "capacités, au moins dans le fragment de son système de type qui accepte de telles choses (pertinent quand il est émulé ala HList / OOHaskell).
Comme je ne connais pas très bien OCaml, je vais donner la partie de votre exemple qui fonctionne en Scala:
Une version pour Haskell dépendrait du système d'enregistrement que vous utilisiez et serait probablement quelque peu maladroite, car elle serait émulée plutôt que prise en charge en mode natif.
Pour autant que je sache, Ceylan a à la fois des types d' intersection et d' union intégrés dans le langage, vous pouvez donc présumer encoder un "xor" de niveau type en termes de ceux-ci.
la source
Java prend en charge les intersections de types d'interface dans certains contextes, bien qu'il ne permette pas pour autant que je sache de créer des variables de types d'intersection. Les types d'intersection peuvent entrer en jeu, par exemple, lors de l'utilisation de l'
? :
opérateur. Si les deuxième et troisième opérandes de cet opérateur sont des interfaces non liées qui héritent des ensembles d'interfaces qui se chevauchent, le résultat de l'opérateur sera l'ensemble d'interfaces communes aux deux.la source
Common Lisp vous permet de définir nouveau type n'utilisant
not
,and
et lesor
opérateurs (voir spécificateurs COMBINANT ).la source