Из любопытства, есть ли языки, которые позволяют вам задавать арифметику для типов для создания новых типов? Что-то вроде:
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()
Я знаю, что в некоторых языках эти идеи могут быть выражены (т. Е. В Java есть List<Comparable & Serializable>
объединение интерфейсов), но я никогда не слышал о языке, который поддерживает арифметику типов. Спасибо!
programming-languages
type-systems
Халдейский коричневый
источник
источник
CanWriteAndCompare extends Serializable, Comparable {}
), И я думал о том, как это обобщить.A
или aB
, с двумя реализациями, которые выглядят абсолютно одинаково. В методе я вызываю полиморфный метод, который может приниматьA
или aB
, поэтому реализации одинаковы, но, поскольку мне нужно взять два разных типа, мне нужны две реализации. Это было бы проще, если бы я мог сделатьmyMethod(A | B aOrB)
.Or
Операция может быть эмулирована множественным наследованием.Ответы:
Tangent ( 0.3 spec ) использует что-то похожее на это. (отказ от ответственности: это мой собственный маленький исследовательский проект)
В настоящее время
with
действует как оператор объединения, моделирующий наследование, хотя прагматизм сделал его некоммутативным. Как только вы вводите реализации в методы, строгое объединение методов с одинаковыми именами часто оказывается не тем, что вы хотите, и все равно невозможно сделать правильно.intersect
поддерживается, что модели выводят тип для чего-то вроде,foo(T,T)
где параметры отличаются.Дополнения были интересными, но приводили к частичным типам, которые казались не такими полезными и / или проблематичными, чтобы правильно их включать - поэтому они не включены.
Я знаю, что есть несколько других исследовательских языков, с которыми мне приходилось сталкиваться, но сейчас я их не помню. Основная проблема заключается в том, что вещи не очень полезны без структурной типизации, которая сама по себе не очень популярна. Другая причина в том, что вам нужен какой-то вид (тип типов) для хранения созданного типа, или это просто сокращение для чего-то, что не особенно идиоматично без этой возможности. И это гораздо реже, чем даже структурная типизация.
Это предвзято, и это не так много, но это так.
источник
Да, Цейлон - это язык со специальными типами объединения и пересечения, как описано в этой главе из тура Цейлона:
Удивительно, сколько крутых идиом вы получаете от этого. Вот один интересный пример, который я недавно опубликовал в блоге . И вот короткая презентация, где я быстро приукрашиваю несколько простых идиом .
Более того, типы объединения / пересечения являются «недостающим звеном», благодаря которому вывод аргументов универсального типа действительно работает правильно на Цейлоне, в отличие от других языков, которые сочетают подтип и параметрический полиморфизм.
Обратите внимание, что существуют ограничения для такого рода «арифметики типов», как вы ее описали. Например, вы не можете иметь оператор дополнения множеством на уровне типов, по крайней мере, без введения неразрешимости.
НТН
источник
Scala поддерживает его частично (пересечения, но не объединения), и любой язык со структурным подтипом (я думаю, OCaml является примером) или система типов, достаточно мощная, чтобы эмулировать это (Haskell является классическим), будет иметь полные «типы как наборы» "возможности, по крайней мере, во фрагменте системы типов, которая принимает такие вещи (уместно, когда она эмулируется как HList / OOHaskell).
Поскольку я не очень хорошо знаю OCaml, я приведу ту часть вашего примера, которая работает в Scala:
Версия для Haskell будет зависеть от используемой вами системы записи и, вероятно, будет несколько неуклюжей, потому что она будет эмулироваться, а не поддерживаться изначально.
Насколько я знаю, в Цейлоне в язык полностью встроены типы пересечений и объединений, так что вы можете предположительно кодировать «xor» на уровне типов в терминах этих.
источник
Java поддерживает пересечения типов интерфейсов в некоторых контекстах, хотя, насколько я могу судить, не позволяет создавать переменные типов пересечений. Типы пересечений могут вступать в игру, например, при использовании
? :
оператора. Если второй и третий операнды этого оператора являются несвязанными интерфейсами, которые наследуются от перекрывающихся наборов интерфейсов, результатом оператора будет набор интерфейсов, которые являются общими для обоих.источник
Common Lisp позволяет вам определить новый тип использования
not
,and
иor
операторы (см Тип спецификаторов, сочетающих ).источник