Jumlah jenis - Mengapa di Haskell adalah `show (Int | Double)` berbeda dari `(show Int) | (tampilkan dobel) `

9

Mengapa ini tidak setara?

show $ if someCondition then someInt else some double

dan

if someCondition then show someInt else show someDouble

Saya mengerti bahwa jika Anda mengisolasi if ... elsebagian dalam contoh pertama ke ekspresi dengan sendirinya maka Anda tidak dapat mewakili tipenya dengan tipe jumlah anonim, jenis Int | Double, seperti sesuatu yang dapat Anda lakukan dengan mudah dalam TypeScript (menyebutkan TypeScript karena itu adalah langauge saya sering menggunakan dan yang mendukung tipe Sum), dan harus menggunakan Eitherdata kemudian berdasarkan itu akan memanggil show.

Contoh yang saya berikan di sini adalah sepele tetapi bagi saya lebih masuk akal untuk berpikir "Oke kita akan menunjukkan sesuatu, dan bahwa sesuatu tergantung pada someCondition" daripada "Okay jika someCondition benar lalu perlihatkan someInt sebaliknya tunjukkan someDouble", dan juga memungkinkan untuk lebih sedikit duplikasi kode (di sini pertunjukan diulang dua kali tetapi bisa juga merupakan aplikasi fungsi yang panjang dan alih-alih if ... elseada> 2 cabang yang perlu dipertimbangkan)

Dalam pikiran saya seharusnya mudah bagi kompiler untuk memeriksa apakah masing-masing jenis yang membuat jumlah jenis (di sini Int | Double) dapat digunakan sebagai parameter untuk showberfungsi dan memutuskan apakah jenis sudah benar atau tidak. Bahkan lebih baik adalah bahwa showfungsi selalu mengembalikan stringapa pun jenis parameternya, sehingga kompiler tidak harus membawa semua "cabang" yang mungkin (jadi semua jenis yang mungkin).

Apakah karena pilihannya fitur seperti itu tidak ada? Atau apakah saya menerapkannya lebih sulit?

Mehdi Saffar
sumber
2
An if ... then ... else ..., harus memiliki tipe thendan elsebagian yang sama. Anda dapat melihatnya sebagai operator ternary dalam beberapa bahasa pemrograman.
Willem Van Onsem
1
Saya setuju tentang making all conversions explicit. Dalam pertanyaan saya, saya tidak ingin Haskell melemparkan Intke Doubleatau sebaliknya. Saya hanya menggunakan dua jenis itu sebagai contoh. Anda dapat mengganti setiap Intdengan adan Doubledengan bpertanyaan saya di mana kedua jenis berasal Show. Saya mengerti bahwa tidak ada anonymous sum typesdi Haskell tapi saya ingin tahu mengapa itu yang terjadi dan apa yang menghentikan kami dari mendesain bahasa untuk memilikinya.
Mehdi Saffar
4
Saya pikir tipe seperti itu disebut tipe union . Tipe penjumlahan pada dasarnya adalah varian tag dari tipe gabungan, di mana setiap nilai harus membawa tag kiri / kanan di luar nilai tipe dalam. Saya berharap inferensi tipe dengan tipe union, dengan semua fitur tipe-level dari Haskell sangat sulit untuk dicapai. Jika x :: Int | Booldan kita harus mengkompilasi show x, tidak ada cara mudah untuk mengetahui fungsi pointer-to mana yang digunakan untuk memanggil show, dalam RTS berbasis tipe-erasure. Kami mungkin perlu menyimpan beberapa informasi tingkat jenis pada saat runtime.
chi
1
Tidak memiliki jenis jumlah anonim adalah keputusan desain desainer Haskell. Saya tidak yakin manfaat apa yang akan mereka bawa ke meja, sedikit saya melihat di mana mereka akan mempersulit. Jadi tebakan saya adalah bahwa mereka ditinggalkan karena rasio biaya / manfaat tidak ada. Tetapi untuk benar-benar yakin Anda perlu bertanya kepada desainer bahasa asli dan / atau pengelola saat ini. Saya tidak berpikir itu akan menjadi pertanyaan SO yang hebat, karena ada banyak pendapat pribadi dan selera yang terlibat dalam mendesain bahasa.
n. 'kata ganti' m.
4
(String, Int)bukan anonim. Ini hanya tipe produk biasa dengan sintaks lucu. (String | Int)akan jauh berbeda. Mulailah dengan bertanya pada diri sendiri apakah (Int|Int)harus identik dengan Intdan mengapa.
n. 'kata ganti' m.

Jawaban:

8

Semua bagian dari ekspresi harus diketik dengan baik. Jenis if someCondition then someInt else someDoubleharus seperti exists a. Show a => a, tetapi Haskell tidak mendukung kuantifikasi eksistensial semacam itu.

Pembaruan: Seperti yang ditunjukkan chi dalam komentar , Haskell juga dimungkinkan jika memiliki dukungan untuk jenis gabungan / persimpangan (yang tidak sama dengan jumlah / jenis produk), tetapi sayangnya tidak.

Joseph Sible-Reinstate Monica
sumber
Bisakah Anda jelaskan perbedaan antara jenis serikat / persimpangan dan jumlah / jenis produk? Saya selalu berpikir mereka sama, kecuali untuk anonimitas?
Mehdi Saffar
1
@MehdiSaffar Anonymous seperti di untagged, bukan sebagai konstruktor yang tidak disebutkan namanya. Dengan kata lain, jika Anda memiliki Int ∪ Double, maka Anda akan tahu bahwa Anda memiliki salah satu dari keduanya, tetapi tidak akan dapat mencocokkan pola untuk melihat yang mana, jadi Anda hanya dapat melakukan hal-hal yang valid untuk kedua kemungkinan tersebut.
Joseph Sible-Reinstate Monica
2
Untuk kejelasan, TypeScript memiliki tipe informasi yang tersedia saat runtime, sehingga ia memiliki typeofoperator yang dapat menebus kurangnya penandaan dan melihat jenis yang digunakan pula. Haskell sepenuhnya terhapus jenis, jadi jika itu mendukung fitur ini, maka tidak akan ada yang setara dengan itu.
Joseph Sible-Reinstate Monica
7

Ada jenis produk dengan sintaks ringan, tertulis (,), di Haskell. Satu hal yang jenis penjumlahan dengan sintaks ringan, seperti (Int | String), akan menjadi ide bagus. Kenyataannya lebih rumit. Mari kita lihat mengapa (saya mengambil beberapa kebebasan Num, mereka tidak penting).

if someCondition then 42 else "helloWorld"

Jika ini mengembalikan nilai tipe (Int | String), lalu apa yang harus dikembalikan berikut?

if someCondition then 42 else 0

(Int | Int)jelas, tetapi jika ini berbeda dari biasa Intmaka kita dalam masalah besar. Jadi (Int | Int)harus identik dengan polos Int.

Orang dapat segera melihat bahwa ini bukan hanya sintaks yang ringan untuk jenis penjumlahan, tetapi fitur bahasa yang sepenuhnya baru. Jenis sistem yang berbeda jika Anda mau. Haruskah kita memilikinya?

Mari kita lihat fungsi ini.

mysteryType x a b = if x then a else b

Sekarang tipe apa yang mysteryTypedimilikinya? Jelas sekali

mysteryType :: Bool -> a -> b -> (a|b)

Baik? Sekarang bagaimana jika adan bapakah jenis yang sama?

let x = mysteryType True 42 0

Ini harus jelas Intseperti yang telah kita sepakati sebelumnya. Sekarang mysteryTypeterkadang kembalikan jenis jumlah anonim, dan terkadang tidak, tergantung pada argumen yang Anda berikan. Bagaimana pola Anda cocok dengan ungkapan seperti itu? Apa yang bisa kamu lakukan dengan itu? Kecuali hal-hal sepele seperti "show" (atau metode apa pun dari kelas-jenis lain yang akan menjadi contoh), tidak banyak. Kecuali jika Anda menambahkan informasi jenis run-time ke bahasa, itu typeofberarti tersedia - dan itu menjadikan Haskell bahasa yang sama sekali berbeda.

Jadi ya. Mengapa Haskell bukan TypeScript? Karena kita tidak memerlukan TypeScript lain. Jika Anda ingin TypeScript, Anda tahu di mana menemukannya.

n. 'kata ganti' m.
sumber
1
@MichaWiedenmann Terus terang saya tidak tahu apakah "relevan" adalah kata yang tepat. Saya pikir ini sangat membantu. Ya saya memang berhenti sejenak dan berpikir apakah akan memasukkannya. Tapi kadang-kadang saya salah.
n. 'kata ganti' m.
Tidak masalah, itu adalah posting Anda, Anda yang memutuskan.
Micha Wiedenmann
Jadi, apa kata ganti Anda?
dfeuer