Por curiosidade, existem idiomas que permitem definir aritmética nos tipos para criar novos 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()
Eu sei que em algumas linguagens essas idéias podem ser expressas (isto é, Java possui List<Comparable & Serializable>
para a união das interfaces), mas nunca ouvi falar de uma linguagem que suporte aritmética de tipo. Obrigado!
programming-languages
type-systems
Castanho Haldean
fonte
fonte
CanWriteAndCompare extends Serializable, Comparable {}
) e eu estava pensando em como generalizar isso.A
ou umB
, com duas implementações que parecem exatamente iguais. No método, estou chamando um método polimórfico que pode levar umA
ou umB
, de modo que as implementações são as mesmas, mas como tenho que usar dois tipos distintos, preciso de duas implementações. Isso seria mais fácil se eu pudesse fazermyMethod(A | B aOrB)
.Or
A operação pode ser emulada por herança múltipla.Respostas:
Tangent ( 0.3 spec ) usa algo parecido com isso. (aviso: este é meu pequeno projeto de pesquisa)
Atualmente,
with
atua como um operador de união que modela a herança, embora o pragmatismo a torne não comutativa. Depois de introduzir implementações nos métodos, uma união estrita de métodos com o mesmo nome geralmente não é o que você deseja e é impossível fazer o que é certo.intersect
É suportado que os modelos digitem inferência para algo comofoo(T,T)
onde os parâmetros são diferentes.Os complementos eram interessantes, mas levavam a tipos parciais que não pareciam tão úteis e / ou problemáticos para serem incluídos corretamente - portanto, não foram incluídos.
Eu sei que existem algumas outras linguagens de pesquisa que encontrei com algo semelhante, mas não consigo lembrar delas no momento. A questão principal é que as coisas não são realmente úteis sem a tipagem estrutural, o que não é muito popular em si. A outra é que você precisa de algum tipo (tipo de tipo) para armazenar o tipo construído, ou então é apenas uma abreviação de algo que não é particularmente idiomático sem esse recurso. E isso é muito menos comum do que a digitação estrutural.
É tendencioso, e não é muito, mas existe.
fonte
Sim, o Ceilão é um idioma com união ad hoc e tipos de interseção, conforme descrito neste capítulo do tour pelo Ceilão:
É incrível o número de expressões legais que você obtém disso. Aqui está um exemplo interessante que eu escrevi recentemente . E aqui está uma breve apresentação em que passo rapidamente por vários idiomas simples .
Melhor ainda, os tipos de união / interseção são o "elo perdido" que faz com que a inferência de argumento de tipo genérico realmente funcione corretamente no Ceilão, em oposição a outros idiomas que combinam subtipo e polimorfismo paramétrico.
Observe que existem limitações para esse tipo de "tipo aritmético", como você o descreveu. Por exemplo, você não pode ter um operador de complemento definido no nível de tipo, pelo menos não sem introduzir indecisão.
HTH
fonte
O Scala o suporta parcialmente (interseções, mas não uniões), e qualquer linguagem com subtipo estrutural (acho que OCaml é um exemplo) ou um sistema de tipos poderoso o suficiente para imitar que (Haskell é um clássico) terá "tipos como conjuntos completos" "capacidades, pelo menos dentro do fragmento de seu sistema de tipos que aceita essas coisas (relevante quando é emulado ala HList / OOHaskell).
Como não conheço muito bem o OCaml, darei a parte do seu exemplo que funciona no Scala:
Uma versão para Haskell dependeria do sistema de registro que você estava usando e provavelmente seria um pouco desajeitada, porque seria emulada e não suportada nativamente.
Tanto quanto eu sei, o Ceilão tem tipos de interseção e união incorporados ao idioma com força total, portanto é possível presumir codificar um "xor" no nível de tipo em termos deles.
fonte
Java suporta interseções de tipos de interface em alguns contextos, embora isso não permita, até onde posso dizer, permitir a criação de variáveis de tipos de interseção. Os tipos de interseção podem entrar em jogo, por exemplo, ao usar o
? :
operador. Se o segundo e o terceiro operandos para esse operador são interfaces não relacionadas que herdam de conjuntos de interfaces sobrepostos, o resultado do operador será o conjunto de interfaces comuns a ambos.fonte
Common Lisp permite que você definir novo tipo usando
not
,and
eor
operadores (ver tipos específicos que Combine ).fonte