Por curiosidad, ¿hay idiomas que le permitan establecer aritmética en tipos para crear nuevos tipos? Algo como:
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()
Sé que en algunos idiomas estas ideas se pueden expresar (es decir, Java tiene List<Comparable & Serializable>
para la unión de las interfaces) pero nunca he oído hablar de un lenguaje que admita aritmética de tipos. ¡Gracias!
programming-languages
type-systems
Marrón Haldean
fuente
fuente
CanWriteAndCompare extends Serializable, Comparable {}
) y estaba pensando en cómo generalizar esto.A
o unaB
, con dos implementaciones que se ven exactamente iguales. En el método, estoy llamando a un método polimórfico que puede tomar unA
o aB
, por lo que las implementaciones son las mismas, pero como tengo que tomar dos tipos distintos, necesito dos implementaciones. Esto sería más fácil si pudiera hacerlomyMethod(A | B aOrB)
.Or
La operación puede ser emulada por herencia múltiple.Respuestas:
Tangent ( espec. 0.3 ) usa algo similar a esto. (descargo de responsabilidad: este es mi propio pequeño proyecto de investigación)
Actualmente
with
actúa como un operador de unión que modela la herencia, aunque el pragmatismo lo ha hecho no conmutativo. Una vez que introduce implementaciones a los métodos, una unión estricta de métodos con el mismo nombre a menudo no es lo que desea e imposible de hacer de todos modos.intersect
Se admite que los modelos tomen inferencia para algo así comofoo(T,T)
donde los parámetros son diferentes.Los complementos fueron interesantes, pero dieron lugar a tipos parciales que no parecían tan útiles y / o problemáticos de incluir correctamente, por lo que no se incluyen.
Sé que hay algunos otros lenguajes de investigación que encontré que tenían algo similar, pero no puedo recordarlos en este momento. El problema principal es que las cosas no son realmente útiles sin la tipificación estructural, que no es muy popular en sí misma. El otro es que necesita algún tipo de tipo (tipo de tipos) para almacenar el tipo construido, o de lo contrario es solo una abreviatura de algo que no es particularmente idiomático sin esa capacidad. Y eso es mucho menos común que incluso la tipificación estructural.
Es parcial y no es mucho, pero ahí está.
fuente
Sí, Ceilán es un lenguaje con tipos de unión e intersección ad hoc, como se describe en este capítulo de la gira de Ceilán:
Es sorprendente la cantidad de expresiones geniales que obtienes de esto. Aquí hay un ejemplo interesante que escribí en un blog recientemente . Y aquí hay una breve presentación donde rápidamente paso por alto varios modismos simples .
Aún mejor, los tipos de unión / intersección son el "eslabón perdido" que hace que la inferencia de argumento de tipo genérico realmente funcione correctamente en Ceilán en comparación con otros lenguajes que combinan subtipo y polimorfismo paramétrico.
Tenga en cuenta que hay limitaciones para este tipo de "tipo aritmético", como lo ha descrito. Por ejemplo, no puede tener un operador de complemento establecido en el nivel de tipo, al menos no sin introducir indecidibilidad.
HTH
fuente
Scala lo admite parcialmente (intersecciones pero no uniones), y cualquier lenguaje con subtipo estructural (creo que OCaml es un ejemplo) o un sistema de tipos lo suficientemente potente como para emular que (Haskell es clásico) tendrá "tipos como conjuntos" completos "capacidades, al menos dentro del fragmento de su sistema de tipos que acepta tales cosas (relevante cuando se emula ala HList / OOHaskell).
Como no conozco muy bien OCaml, daré la parte de su ejemplo que funciona en Scala:
Una versión para Haskell dependería del sistema de registro que estaba utilizando, y probablemente sería algo torpe, porque sería emulada en lugar de ser compatible de forma nativa.
Hasta donde yo sé, Ceilán tiene tipos de intersección y unión integrados en el lenguaje con toda su potencia, por lo que presumiblemente podría codificar un "xor" de nivel de tipo en términos de esos.
fuente
Java admite intersecciones de tipos de interfaz en algunos contextos, aunque, por lo que puedo decir, no permite la creación de variables de tipos de intersección. Los tipos de intersección pueden entrar en juego, por ejemplo, cuando se usa el
? :
operador. Si el segundo y tercer operandos a ese operador son interfaces no relacionadas que heredan de conjuntos de interfaces superpuestos, el resultado del operador será el conjunto de interfaces que son comunes a ambos.fuente
Common Lisp permite que usted defina nuevo tipo usando
not
,and
yor
operadores (ver especificadores de tipo que combinan ).fuente