Apakah ada bahasa pemrograman yang memungkinkan Anda melakukan set aritmatika pada tipe?

9

Karena penasaran, apakah ada bahasa yang memungkinkan Anda melakukan set aritmatika pada jenis untuk membuat jenis baru? Sesuatu seperti:

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()

Saya tahu bahwa dalam beberapa bahasa ide-ide ini dapat diekspresikan (yaitu, Java memiliki List<Comparable & Serializable>untuk penyatuan antarmuka) tetapi saya belum pernah mendengar bahasa yang mendukung tipe aritmatika. Terima kasih!

Brown Haldean
sumber
7
Bagaimana mekanisme seperti itu berguna?
Robert Harvey
4
Sebuah pola yang sering saya lihat adalah antarmuka yang memperluas dua antarmuka lain dan tidak menambahkan apa pun (yaitu, CanWriteAndCompare extends Serializable, Comparable {}) dan saya sedang memikirkan cara menggeneralisasi ini.
Haldean Brown
2
Juga, saya mengalami kasus hari ini di mana saya memiliki metode yang dapat mengambil satu Aatau dua B, dengan dua implementasi yang terlihat persis sama. Dalam metode ini saya memanggil metode polimorfik yang dapat mengambil Aatau B, jadi implementasinya sama, tetapi karena saya harus mengambil dua tipe yang berbeda, saya perlu dua implementasi. Ini akan lebih mudah jika saya bisa melakukannya myMethod(A | B aOrB).
Haldean Brown
1
Lihat di sini: msdn.microsoft.com/en-us/library/4taxa8t2.aspx
Robert Harvey
1
Oroperasi dapat ditiru oleh banyak pewarisan.
pengguna

Jawaban:

4

Tangent ( 0,3 spec ) menggunakan sesuatu yang mirip dengan ini. (Penafian: ini adalah proyek penelitian kecil saya sendiri)

Saat ini withbertindak sebagai pewaris operator serikat pemodelan, meskipun pragmatisme membuatnya tidak komutatif. Setelah Anda memperkenalkan implementasi ke metode, penyatuan metode yang ketat dengan nama yang sama seringkali bukan yang Anda inginkan dan tidak mungkin dilakukan dengan benar.

intersectdidukung bahwa model mengetik inferensi untuk sesuatu seperti di foo(T,T)mana parameternya berbeda.

Komplemennya menarik, tetapi menyebabkan tipe parsial yang tampaknya tidak begitu berguna dan / atau sulit untuk dimasukkan dengan benar - jadi tidak disertakan.

Saya tahu ada beberapa bahasa penelitian lain yang saya temui yang memiliki sesuatu yang serupa, tetapi tidak dapat mengingatnya saat ini. Masalah utama adalah bahwa hal-hal itu tidak benar-benar berguna tanpa pengetikan struktural, yang tidak terlalu populer itu sendiri. Yang lain adalah bahwa Anda memerlukan semacam (jenis jenis) untuk menyimpan jenis yang dibangun, atau hanya singkatan untuk sesuatu yang tidak terlalu idiomatis tanpa kemampuan itu. Dan itu jauh lebih jarang daripada mengetik struktural.

Itu bias, dan tidak banyak, tapi itu ada.

Telastyn
sumber
5

Ya, Ceylon adalah bahasa dengan jenis penyatuan dan persimpangan ad hoc, seperti dijelaskan dalam bab ini dari tur Ceylon:

http://ceylon-lang.org/documentation/1.0/tour/types/

Sungguh menakjubkan jumlah idiom keren yang Anda dapatkan dari ini. Inilah salah satu contoh menarik yang saya blog baru-baru ini . Dan inilah presentasi singkat di mana saya dengan cepat mengabaikan beberapa idiom sederhana .

Bahkan yang lebih baik, tipe gabungan / persimpangan adalah "tautan yang hilang" yang membuat inferensi argumen tipe generik benar-benar berfungsi dengan baik di Ceylon dibandingkan dengan bahasa lain yang menggabungkan subtipe dan polimorfisme parametrik.

Perhatikan bahwa ada batasan untuk "tipe aritmatika" semacam ini, seperti yang telah Anda gambarkan. Misalnya, Anda tidak dapat memiliki satu set operator pelengkap di tingkat tipe, setidaknya tidak tanpa memperkenalkan keraguan.

HTH

Gavin King
sumber
3

Scala mendukungnya sebagian (persimpangan tetapi bukan serikat pekerja), dan bahasa apa pun dengan subtipe struktural (saya pikir OCaml adalah contoh) atau sistem tipe yang cukup kuat untuk meniru itu (Haskell adalah yang klasik) akan memiliki "tipe-as-set" penuh "kapabilitas, setidaknya dalam fragmen sistem tipenya yang menerima hal-hal seperti itu (relevan ketika ditiru secara HList / OOHaskell).

Karena saya tidak mengenal OCaml dengan baik, saya akan memberikan bagian dari contoh Anda yang berfungsi di Scala:

trait A {
  def a(): Unit
  def b(): Unit
}

abstract class B { // just to prove it works with both traits and classes
  def b(): Unit
  def c(): Unit
}

type C = A with B
type D = { def b(): Unit } // not an exact translation, because unions aren't directly available
// type `E` is unrepresentable

Versi untuk Haskell akan bergantung pada sistem rekaman yang Anda gunakan, dan kemungkinan akan agak kikuk, karena itu akan ditiru daripada didukung secara native.

Sejauh yang saya tahu, Ceylon memiliki tipe persimpangan dan gabungan yang dibangun ke dalam bahasa dengan kekuatan penuh, sehingga Anda mungkin dapat menyandikan "xor" tipe-level dalam hal itu.

Api Ptharien
sumber
1

Java mendukung persimpangan tipe antarmuka dalam beberapa konteks, meskipun tidak sejauh yang saya tahu memungkinkan pembuatan variabel tipe persimpangan. Jenis titik-temu mungkin ikut berperan, misalnya saat menggunakan ? :operator. Jika operan kedua dan ketiga ke operator itu adalah antarmuka yang tidak terkait yang mewarisi dari set antarmuka yang tumpang tindih, hasil dari operator akan menjadi set antarmuka yang umum untuk keduanya.

supercat
sumber