Saya telah melihat beberapa sumber menggemakan pendapat bahwa "Haskell secara bertahap menjadi bahasa yang diketik secara dependen". Implikasinya tampaknya bahwa dengan semakin banyak ekstensi bahasa, Haskell melayang ke arah yang umum, tetapi belum ada di sana.
Pada dasarnya ada dua hal yang ingin saya ketahui. Yang pertama adalah, cukup sederhana, apa "yang bahasa dependen-mengetik" benar-benar berarti ? (Semoga tanpa terlalu teknis tentang hal itu.)
Pertanyaan kedua adalah ... apa kekurangannya? Maksudku, orang tahu kita menuju ke sana, jadi pasti ada keuntungannya. Namun, kita belum sampai di sana, jadi pasti ada beberapa hal buruk yang membuat orang berhenti. Saya mendapat kesan bahwa masalahnya adalah peningkatan kompleksitas yang curam. Tapi, tidak benar-benar memahami apa yang dimaksud dengan mengetik, saya tidak tahu pasti.
Apa yang saya lakukan tahu adalah bahwa setiap kali saya mulai membaca tentang bahasa pemrograman dependen-diketik, teks sama sekali tidak bisa dimengerti ... Agaknya itulah masalahnya. (?)
sumber
Jawaban:
Pengetikan dependen sebenarnya hanya penyatuan nilai dan tingkat tipe, sehingga Anda dapat menentukan nilai pada tipe (sudah dimungkinkan dengan kelas tipe dan polimorfisme parametrik di Haskell) dan Anda dapat menentukan tipe pada nilai (tidak, secara tegas, mungkin di Haskell , meskipun
DataKinds
sangat dekat).Sunting: Rupanya, sejak saat ini, saya salah (lihat komentar @ pigworker). Saya akan melestarikan sisanya sebagai catatan mitos yang telah saya makan. : P
Masalah dengan pindah ke pengetikan sepenuhnya tergantung, dari apa yang saya dengar, adalah bahwa itu akan mematahkan pembatasan fase antara jenis dan tingkat nilai yang memungkinkan Haskell dikompilasi ke kode mesin yang efisien dengan tipe yang terhapus. Dengan tingkat teknologi kami saat ini, bahasa yang diketik secara dependen harus melalui penerjemah di beberapa titik (baik segera, atau setelah dikompilasi ke bytecode yang diketik-tergantung atau serupa).
Ini belum tentu merupakan batasan mendasar, tetapi saya secara pribadi tidak mengetahui adanya penelitian saat ini yang terlihat menjanjikan dalam hal ini, tetapi belum membuatnya menjadi GHC. Jika ada orang lain yang tahu lebih banyak, saya akan senang dikoreksi.
sumber
Mengetik Haskell dengan Ketergantungan, Sekarang?
Haskell, sebagian kecil, adalah bahasa yang diketik secara dependen. Ada gagasan tentang tipe data tingkat, sekarang lebih masuk akal mengetik berkat
DataKinds
, dan ada beberapa cara (GADTs
) untuk memberikan representasi run-time untuk data tipe tingkat. Oleh karena itu, nilai run-time stuff secara efektif muncul dalam tipe , yang artinya apa yang harus diketik dalam bahasa.Tipe data sederhana dipromosikan ke tingkat jenis, sehingga nilai yang dikandungnya dapat digunakan dalam jenis. Karena itulah contoh pola dasar
menjadi mungkin, dan dengan itu, definisi seperti
itu bagus. Perhatikan bahwa panjangnya
n
adalah hal yang murni statis dalam fungsi itu, memastikan bahwa vektor input dan output memiliki panjang yang sama, meskipun panjang itu tidak berperan dalam eksekusivApply
. Sebaliknya, itu jauh lebih sulit (yaitu, tidak mungkin) untuk melaksanakan fungsi yang membuatn
salinan yang diberikanx
(yang akanpure
kevApply
's<*>
)karena sangat penting untuk mengetahui berapa banyak salinan yang harus dibuat pada saat run-time. Masukkan lajang.
Untuk semua jenis yang dapat dipromosikan, kita dapat membangun keluarga tunggal, diindeks dari jenis yang dipromosikan, dihuni oleh duplikat run-time dari nilainya.
Natty n
adalah jenis salinan run-time dari tipe-leveln :: Nat
. Kita sekarang bisa menulisJadi, di sana Anda memiliki nilai level-tipe yang dipasangkan ke nilai run-time: memeriksa salinan run-time memurnikan pengetahuan statis tentang nilai level-tipe. Meskipun istilah dan jenisnya terpisah, kita dapat bekerja dengan cara yang diketik secara dependen dengan menggunakan konstruksi tunggal sebagai semacam resin epoksi, menciptakan ikatan di antara fase-fase tersebut. Itu jauh dari memungkinkan ekspresi run-time sewenang-wenang dalam jenis, tapi itu bukan apa-apa.
Apa itu Nasty? Apa yang hilang?
Mari kita beri sedikit tekanan pada teknologi ini dan lihat apa yang mulai goyah. Kita mungkin mendapat gagasan bahwa lajang harus dikelola sedikit lebih implisit
memungkinkan kita untuk menulis, katakan,
Itu bekerja, tetapi sekarang berarti bahwa
Nat
tipe asli kami telah menghasilkan tiga salinan: sejenis, keluarga tunggal dan kelas tunggal. Kami memiliki proses yang agak kikuk untuk bertukarNatty n
nilai danNattily n
kamus eksplisit . Selain itu,Natty
tidakNat
: kita memiliki semacam ketergantungan pada nilai run-time, tetapi tidak pada jenis yang pertama kali kita pikirkan. Tidak ada bahasa yang diketik sepenuhnya tergantung membuat jenis dependen ini rumit!Sementara itu, meski
Nat
bisa dipromosikan,Vec
tidak bisa. Anda tidak dapat mengindeks berdasarkan tipe yang diindeks. Penuh pada bahasa yang diketik secara dependen tidak memberlakukan batasan seperti itu, dan dalam karier saya sebagai pamer yang diketik secara dependen, saya telah belajar untuk menyertakan contoh pengindeksan dua lapis dalam pembicaraan saya, hanya untuk mengajar orang-orang yang telah membuat pengindeksan satu lapis sulit-tetapi-mungkin untuk tidak mengharapkan saya melipat seperti rumah kartu. Apa masalahnya? Persamaan. GADT bekerja dengan menerjemahkan kendala yang Anda capai secara implisit ketika Anda memberikan konstruktor tipe pengembalian spesifik ke dalam tuntutan persamaan eksplisit. Seperti ini.Di masing-masing dari dua persamaan kami, kedua belah pihak memiliki jenis
Nat
.Sekarang coba terjemahan yang sama untuk sesuatu yang diindeks oleh vektor.
menjadi
dan sekarang kita membentuk kendala persamaan antara
as :: Vec n x
dan diVCons z zs :: Vec (S m) x
mana kedua belah pihak memiliki jenis yang berbeda secara sintaksis (tetapi terbukti sama). Inti GHC saat ini tidak dilengkapi untuk konsep seperti itu!Apa lagi yang hilang? Yah, sebagian besar Haskell hilang dari level tipenya. Bahasa istilah yang dapat Anda promosikan benar-benar memiliki variabel dan konstruktor non-GADT. Setelah Anda memilikinya,
type family
mesinnya memungkinkan Anda untuk menulis program level-type: beberapa di antaranya mungkin sangat mirip dengan fungsi yang Anda pertimbangkan untuk menulis pada level term (misalnya, melengkapiNat
dengan penambahan, sehingga Anda dapat memberikan tipe yang bagus untuk ditambahkanVec
) , tapi itu hanya kebetulan!Hal lain yang hilang, dalam praktiknya, adalah perpustakaan yang memanfaatkan kemampuan baru kami untuk mengindeks tipe berdasarkan nilai. Apa yang terjadi
Functor
danMonad
menjadi di dunia baru yang berani ini? Saya sedang memikirkannya, tetapi masih banyak yang harus dilakukan.Menjalankan Program Level-Type
Haskell, seperti kebanyakan bahasa pemrograman yang diketik secara dependen, memiliki dua semantik operasional. Ada cara sistem run-time menjalankan program (hanya ekspresi tertutup, setelah penghapusan tipe, sangat dioptimalkan) dan kemudian ada cara typechecker menjalankan program (keluarga tipe Anda, "jenis kelas Prolog", dengan ekspresi terbuka). Untuk Haskell, Anda biasanya tidak mencampur keduanya, karena program yang dijalankan dalam bahasa yang berbeda. Bahasa ketergantungan diketik memiliki terpisah run-time dan model eksekusi statis untuk sama bahasa program, tapi jangan khawatir, model run-time masih memungkinkan Anda melakukan penghapusan jenis dan, memang, bukti penghapusan: yang ini apa Coq ini ekstraksimekanisme memberi Anda; setidaknya itulah yang dikompilasi oleh Edwin Brady (walaupun Edwin menghapus nilai-nilai yang tidak perlu, juga tipe dan bukti). Perbedaan fase mungkin bukan perbedaan kategori sintaksis lagi, tapi itu hidup dan sehat.
Bahasa yang diketik dengan tergantung, sebagai total, memungkinkan juru ketik untuk menjalankan program bebas dari rasa takut akan sesuatu yang lebih buruk daripada menunggu lama. Ketika Haskell menjadi lebih sering diketik, kita menghadapi pertanyaan seperti apa model eksekusi statisnya? Salah satu pendekatan mungkin untuk membatasi eksekusi statis untuk fungsi total, yang akan memungkinkan kita untuk menjalankan kebebasan yang sama, tetapi mungkin memaksa kita untuk membuat perbedaan (setidaknya untuk kode tingkat-jenis) antara data dan codata, sehingga kita dapat menentukan apakah harus memberlakukan pemutusan hubungan kerja atau produktivitas. Tapi itu bukan satu-satunya pendekatan. Kita bebas memilih model pelaksanaan yang jauh lebih lemah yang enggan menjalankan program, dengan biaya membuat lebih sedikit persamaan yang keluar hanya dengan perhitungan. Dan sebenarnya, itulah yang sebenarnya dilakukan GHC. Aturan pengetikan untuk inti GHC tidak menyebutkan menjalankan program, tetapi hanya untuk memeriksa bukti untuk persamaan. Saat menerjemahkan ke inti, pemecah kendala GHC mencoba menjalankan program level-type Anda, menghasilkan sedikit jejak bukti keperakan bahwa ekspresi yang diberikan sama dengan bentuk normalnya. Metode pembuktian-bukti ini sedikit tidak dapat diprediksi dan tidak bisa dihindari: metode ini berjuang melawan rekursi yang tampak menakutkan, misalnya, dan itu mungkin bijaksana. Satu hal yang tidak perlu kita khawatirkan adalah pelaksanaan
IO
perhitungan di typechecker: ingat bahwa typechecker tidak harus memberikanlaunchMissiles
arti yang sama dengan sistem run-time!Budaya Hindley-Milner
Sistem tipe Hindley-Milner mencapai kebetulan yang benar-benar luar biasa dari empat perbedaan yang berbeda, dengan efek samping budaya yang disayangkan bahwa banyak orang tidak dapat melihat perbedaan antara perbedaan dan menganggap kebetulan itu tidak bisa dihindari! Apa yang saya bicarakan?
Kami terbiasa menulis istilah dan meninggalkan jenis yang akan disimpulkan ... lalu dihapus. Kami terbiasa menghitung variabel tipe dengan abstraksi tipe yang sesuai dan aplikasi terjadi secara diam-diam dan statis.
Anda tidak perlu membelok terlalu jauh dari vanilla Hindley-Milner sebelum perbedaan ini tidak selaras, dan itu bukan hal yang buruk . Sebagai permulaan, kita dapat memiliki jenis yang lebih menarik jika kita bersedia menulisnya di beberapa tempat. Sementara itu, kita tidak harus menulis kamus kelas ketik ketika kita menggunakan fungsi-fungsi yang kelebihan beban, tetapi kamus-kamus itu pasti ada (atau sebaris) pada saat run-time. Dalam bahasa yang diketik secara dependen, kami berharap untuk menghapus lebih dari sekadar tipe saat run-time, tetapi (seperti dengan kelas tipe) bahwa beberapa nilai yang disimpulkan secara implisit tidak akan dihapus. Misalnya,
vReplicate
argumen numerik seringkali dapat disimpulkan dari jenis vektor yang diinginkan, tetapi kita masih perlu mengetahuinya pada saat run-time.Pilihan desain bahasa mana yang harus kita tinjau karena kebetulan ini tidak lagi berlaku? Misalnya, apakah benar Haskell tidak memberikan cara untuk membuat instance
forall x. t
quantifier secara eksplisit? Jika typechecker tidak dapat menebakx
dengan menyatukant
, kami tidak memiliki cara lain untuk mengatakan apa yangx
harus terjadi.Secara lebih luas, kita tidak bisa memperlakukan "inferensi tipe" sebagai konsep monolitik yang kita miliki semuanya atau tidak sama sekali. Sebagai permulaan, kita perlu memisahkan aspek "generalisasi" (aturan "biarkan" Milner), yang sangat bergantung pada pembatasan jenis mana yang ada untuk memastikan bahwa mesin bodoh dapat menebak satu, dari aspek "spesialisasi" (Milner's "var "rule) yang sama efektifnya dengan pemecah kendala Anda. Kita dapat berharap bahwa tipe tingkat atas akan menjadi lebih sulit untuk disimpulkan, tetapi informasi tipe internal akan tetap cukup mudah untuk disebarkan.
Langkah Selanjutnya Untuk Haskell
Kami melihat jenis dan tingkat jenis tumbuh sangat mirip (dan mereka sudah berbagi representasi internal di GHC). Kita mungkin juga menggabungkan mereka. Akan menyenangkan untuk mengambil
* :: *
jika kita bisa: kita kehilangan kesehatan logis sejak lama, ketika kita membiarkan bagian bawah, tetapi jenis kesehatan biasanya merupakan persyaratan yang lebih lemah. Kita harus periksa. Jika kita harus memiliki tipe, jenis, dan level yang berbeda, kita setidaknya dapat memastikan semuanya pada level tipe dan di atas selalu dapat dipromosikan. Alangkah baiknya hanya menggunakan kembali polimorfisme yang sudah kita miliki untuk tipe, daripada menciptakan kembali polimorfisme pada tingkat jenis.Kita harus menyederhanakan dan menggeneralisasi sistem kendala saat ini dengan memungkinkan persamaan heterogen di
a ~ b
mana jenisa
danb
tidak identik secara sintaksis (tetapi dapat dibuktikan sama). Ini adalah teknik lama (dalam tesis saya, abad lalu) yang membuat ketergantungan jauh lebih mudah untuk diatasi. Kami dapat mengekspresikan kendala pada ekspresi di GADT, dan dengan demikian melonggarkan pembatasan pada apa yang dapat dipromosikan.Kita harus menghilangkan kebutuhan untuk konstruksi tunggal dengan memperkenalkan tipe fungsi dependen
pi x :: s -> t
,. Fungsi dengan tipe seperti itu dapat diterapkan secara eksplisit pada ekspresi tipe apa puns
yang hidup di persimpangan jenis dan istilah bahasa (jadi, variabel, konstruktor, dengan lebih banyak yang akan datang nanti). Lambda dan aplikasi yang sesuai tidak akan dihapus pada saat run-time, jadi kami akan dapat menulistanpa mengganti
Nat
denganNatty
. Domainpi
dapat berupa jenis apa pun yang dapat dipromosikan, jadi jika GADT dapat dipromosikan, kita dapat menulis sekuens kuantifier dependen (atau "teleskop" seperti yang disebut de Briuijn)sejauh apa pun yang kita butuhkan.
Inti dari langkah-langkah ini adalah untuk menghilangkan kerumitan dengan bekerja secara langsung dengan alat yang lebih umum, alih-alih puas dengan alat yang lemah dan penyandian yang kikuk. Dukungan parsial saat ini membuat manfaat tipe dependen Haskell lebih mahal daripada yang seharusnya.
Terlalu keras?
Jenis ketergantungan membuat banyak orang gelisah. Mereka membuat saya gugup, tetapi saya suka gugup, atau setidaknya saya merasa sulit untuk tidak gugup. Tapi itu tidak membantu bahwa ada kabut ketidaktahuan di sekitar topik tersebut. Beberapa di antaranya karena kenyataan bahwa kita semua masih harus banyak belajar. Namun para pendukung pendekatan yang kurang radikal diketahui memicu rasa takut terhadap tipe-tipe dependen tanpa selalu memastikan fakta sepenuhnya ada pada mereka. Saya tidak akan menyebutkan nama. Ini "pemeriksaan ketik yang tidak dapat ditentukan", "Turing tidak lengkap", "tidak ada perbedaan fasa", "tidak ada penghapusan tipe", "bukti di mana-mana", dll, mitos tetap ada, meskipun itu adalah sampah.
Ini tentu bukan kasus bahwa program yang diketik secara dependen harus selalu terbukti benar. Seseorang dapat meningkatkan kebersihan dasar dari program seseorang, memberlakukan invarian tambahan dalam jenis tanpa pergi ke spesifikasi lengkap. Langkah-langkah kecil ke arah ini cukup sering menghasilkan jaminan yang lebih kuat dengan sedikit atau tanpa kewajiban bukti tambahan. Tidak benar bahwa program-program yang diketik secara tergantung pasti penuh dengan bukti, memang saya biasanya mengambil keberadaan bukti dalam kode saya sebagai isyarat untuk mempertanyakan definisi saya .
Karena, seperti halnya dengan peningkatan dalam artikulasi, kita menjadi bebas untuk mengatakan hal-hal baru yang buruk serta adil. Misalnya, ada banyak cara payah untuk mendefinisikan pohon pencarian biner, tetapi itu tidak berarti tidak ada cara yang baik . Sangat penting untuk tidak menganggap bahwa pengalaman buruk tidak bisa lebih baik, bahkan jika ego menolaknya. Desain definisi dependen adalah keterampilan baru yang membutuhkan pembelajaran, dan menjadi programmer Haskell tidak secara otomatis membuat Anda menjadi seorang ahli! Dan bahkan jika beberapa program curang, mengapa Anda menolak orang lain kebebasan untuk adil?
Kenapa Masih Mengganggu Haskell?
Saya sangat menikmati tipe dependen, tetapi sebagian besar proyek peretasan saya masih di Haskell. Mengapa? Haskell memiliki kelas tipe. Haskell memiliki perpustakaan yang bermanfaat. Haskell memiliki perawatan pemrograman yang bisa diterapkan (walaupun jauh dari ideal) dengan efek. Haskell memiliki kompiler kekuatan industri. Bahasa yang diketik secara dependen berada pada tahap yang jauh lebih awal dalam menumbuhkan komunitas dan infrastruktur, tetapi kita akan sampai di sana, dengan perubahan generasi nyata dalam apa yang mungkin, misalnya, dengan cara pemrograman dan generik tipe data. Tetapi Anda hanya perlu melihat-lihat apa yang dilakukan orang sebagai hasil dari langkah-langkah Haskell menuju tipe-tipe dependen untuk melihat bahwa ada banyak manfaat yang bisa diperoleh dengan mendorong generasi bahasa sekarang ke depan juga.
sumber
fmap read getLine >>= \n -> vReplicate n 0
. Seperti yang Anda perhatikan,Natty
ada cara untuk menjauh dari ini. Selain itu, vReplicate harus diterjemahkan ke array memori yang sebenarnya, sesuatu sepertinewtype SVector n x = SVector (Data.Vector.Vector x)
, di manan
memiliki jenisNat
(atau serupa). Mungkin titik demonstrasi lain untuk "pamer ketergantungan-mengetik?"John itu kesalahpahaman umum lain tentang tipe dependen: bahwa mereka tidak berfungsi ketika data hanya tersedia saat run-time. Inilah cara Anda dapat melakukan contoh getLine:
Sunting: Hm, itu seharusnya menjadi komentar untuk jawaban pekerja tambang. Saya jelas gagal di SO.
sumber
Vec Zy -> IO String
. Anda tidak dapat menggunakannya denganwithZeroes
, karena jenisnyaZy
tidak dapat disatukan dengan forall n. Mungkin Anda bisa mengatasinya untuk satu atau dua kasus khusus, tetapi cepat hilang kendali.forall n
masuk akal. Pembatasan yang lebih tepat dapat diterapkan dengan cara yang sama. Apakah Anda memiliki contoh yang lebih baik daripadaVec Zy
(program masih perlu menangani pengguna memasukkan 5 daripada 0)?Vec Zy -> IO String
dan yang lain untukVec n -> IO String
, dan Anda ingin menggunakan yang pertama hanya jika jenisnya cocok. Ya itu mungkin, tetapi mekanisme untuk mengaktifkannya kikuk. Dan ini adalah logika yang sangat sederhana; jika Anda memiliki logika yang lebih kompleks, itu lebih buruk. Juga, Anda mungkin perlu menulis ulang banyak kode dalam CPS. Dan Anda masih belum memiliki ekspresi tipe-level yang bergantung pada istilah pada level nilaizeroes :: IO (Some (Flip Vec Int))
.Pigworker memberikan diskusi yang bagus tentang mengapa kita harus menuju pada tipe-tipe dependen: (a) mereka mengagumkan; (b) mereka sebenarnya akan menyederhanakan banyak hal yang sudah dilakukan Haskell.
Adapun "mengapa tidak?" pertanyaan, ada beberapa poin yang saya pikir. Poin pertama adalah bahwa sementara gagasan dasar di balik tipe dependen mudah (memungkinkan tipe bergantung pada nilai-nilai), konsekuensi dari gagasan dasar tersebut halus dan mendalam. Sebagai contoh, perbedaan antara nilai dan tipe masih hidup dan baik; tetapi mendiskusikan perbedaan di antara mereka menjadi jauhlebih bernuansa daripada di Hindley Anda - Milner atau Sistem F. Untuk beberapa hal ini disebabkan oleh fakta bahwa tipe dependen secara fundamental sulit (misalnya, logika tingkat pertama tidak dapat diputuskan). Tapi saya pikir masalah yang lebih besar adalah kita tidak memiliki kosakata yang baik untuk menangkap dan menjelaskan apa yang terjadi. Semakin banyak orang belajar tentang tipe dependen, kami akan mengembangkan kosakata yang lebih baik dan hal-hal akan menjadi lebih mudah untuk dipahami, bahkan jika masalah yang mendasarinya masih sulit.
Poin kedua berkaitan dengan fakta bahwa Haskell adalah tumbuhmenuju tipe dependen. Karena kami membuat kemajuan bertahap ke arah tujuan itu, tetapi tanpa benar-benar membuatnya di sana, kami terjebak dengan bahasa yang memiliki tambalan tambahan di atas tambalan tambahan. Hal yang sama telah terjadi dalam bahasa lain ketika ide-ide baru menjadi populer. Java tidak terbiasa memiliki polimorfisme (parametrik); dan ketika mereka akhirnya menambahkannya, itu jelas merupakan peningkatan bertahap dengan beberapa kebocoran abstraksi dan daya yang lumpuh. Ternyata, mencampur subtipe dan polimorfisme pada dasarnya sulit; tapi itu bukan alasan mengapa Java Generics bekerja seperti yang mereka lakukan. Mereka bekerja dengan cara yang mereka lakukan karena kendala untuk menjadi peningkatan tambahan untuk versi Java yang lebih lama. Ditto, untuk lebih jauh ke belakang pada hari ketika OOP ditemukan dan orang-orang mulai menulis "obyektif" C (jangan bingung dengan Objective-C), dll. Ingat, C ++ dimulai dengan kedok menjadi superset ketat dari C. Menambahkan paradigma baru selalu membutuhkan pendefinisian bahasa yang baru, atau berakhir dengan kekacauan yang rumit. Maksud saya dalam semua ini adalah bahwa, menambahkan tipe dependen yang sebenarnya ke Haskell akan membutuhkan sejumlah gutting dan restrukturisasi bahasa --- jika kita akan melakukannya dengan benar. Tetapi sangat sulit untuk melakukan perbaikan seperti itu, sedangkan kemajuan yang kami buat tampaknya lebih murah dalam jangka pendek. Sungguh, tidak banyak orang yang meretas GHC, tetapi ada sejumlah kode warisan yang cukup untuk tetap hidup. Ini adalah bagian dari alasan mengapa ada begitu banyak bahasa spin-off seperti DDC, Cayenne, Idris, dll. C ++ dimulai dengan kedok sebagai superset ketat dari C. Menambahkan paradigma baru selalu membutuhkan pendefinisian bahasa yang baru, atau berakhir dengan kekacauan yang rumit. Maksud saya dalam semua ini adalah bahwa, menambahkan tipe dependen yang sebenarnya ke Haskell akan membutuhkan sejumlah gutting dan restrukturisasi bahasa --- jika kita akan melakukannya dengan benar. Tetapi sangat sulit untuk melakukan perbaikan seperti itu, sedangkan kemajuan yang kami buat tampaknya lebih murah dalam jangka pendek. Sungguh, tidak banyak orang yang meretas GHC, tetapi ada sejumlah kode warisan yang cukup untuk tetap hidup. Ini adalah bagian dari alasan mengapa ada begitu banyak bahasa spin-off seperti DDC, Cayenne, Idris, dll. C ++ dimulai dengan kedok sebagai superset ketat dari C. Menambahkan paradigma baru selalu membutuhkan pendefinisian bahasa yang baru, atau berakhir dengan kekacauan yang rumit. Maksud saya dalam semua ini adalah bahwa, menambahkan tipe dependen yang sebenarnya ke Haskell akan membutuhkan sejumlah gutting dan restrukturisasi bahasa --- jika kita akan melakukannya dengan benar. Tetapi sangat sulit untuk melakukan perbaikan seperti itu, sedangkan kemajuan yang kami buat tampaknya lebih murah dalam jangka pendek. Sungguh, tidak banyak orang yang meretas GHC, tetapi ada sejumlah kode warisan yang cukup untuk tetap hidup. Ini adalah bagian dari alasan mengapa ada banyak bahasa spin-off seperti DDC, Cayenne, Idris, dll. atau berakhir dengan kekacauan yang rumit. Maksud saya dalam semua ini adalah bahwa, menambahkan tipe dependen yang sebenarnya ke Haskell akan membutuhkan sejumlah gutting dan restrukturisasi bahasa --- jika kita akan melakukannya dengan benar. Tetapi sangat sulit untuk melakukan perbaikan seperti itu, sedangkan kemajuan yang kami buat tampaknya lebih murah dalam jangka pendek. Sungguh, tidak banyak orang yang meretas GHC, tetapi ada sejumlah kode warisan yang cukup untuk tetap hidup. Ini adalah bagian dari alasan mengapa ada begitu banyak bahasa spin-off seperti DDC, Cayenne, Idris, dll. atau berakhir dengan kekacauan yang rumit. Maksud saya dalam semua ini adalah bahwa, menambahkan tipe dependen yang sebenarnya ke Haskell akan membutuhkan sejumlah gutting dan restrukturisasi bahasa --- jika kita akan melakukannya dengan benar. Tetapi sangat sulit untuk melakukan perbaikan seperti itu, sedangkan kemajuan yang kami buat tampaknya lebih murah dalam jangka pendek. Sungguh, tidak banyak orang yang meretas GHC, tetapi ada sejumlah kode warisan yang cukup untuk tetap hidup. Ini adalah bagian dari alasan mengapa ada begitu banyak bahasa spin-off seperti DDC, Cayenne, Idris, dll. Sangat sulit untuk berkomitmen pada perbaikan semacam itu, sedangkan kemajuan tambahan yang kami buat tampaknya lebih murah dalam jangka pendek. Sungguh, tidak banyak orang yang meretas GHC, tetapi ada sejumlah kode warisan yang cukup untuk tetap hidup. Ini adalah bagian dari alasan mengapa ada begitu banyak bahasa spin-off seperti DDC, Cayenne, Idris, dll. Sangat sulit untuk berkomitmen pada perbaikan semacam itu, sedangkan kemajuan tambahan yang kami buat tampaknya lebih murah dalam jangka pendek. Sungguh, tidak banyak orang yang meretas GHC, tetapi ada sejumlah kode warisan yang cukup untuk tetap hidup. Ini adalah bagian dari alasan mengapa ada begitu banyak bahasa spin-off seperti DDC, Cayenne, Idris, dll.
sumber