Apakah varian Lisp lengkap yang diketik secara statis dimungkinkan? Apakah masuk akal jika sesuatu seperti ini ada? Saya percaya salah satu keutamaan bahasa Lisp adalah kesederhanaan definisinya. Apakah pengetikan statis akan mengganggu prinsip inti ini?
programming-languages
lisp
static-typing
Lambda yang Kedua dari Belakang
sumber
sumber
Jawaban:
Ya, itu sangat mungkin, meskipun sistem tipe HM-style standar biasanya merupakan pilihan yang salah untuk sebagian besar kode Lisp / Skema idiomatik. Lihat Typed Racket untuk bahasa terkini yaitu "Full Lisp" (lebih mirip Scheme, sebenarnya) dengan pengetikan statis.
sumber
Sexpr
.coerce :: a->b
dalam istilah eval. Dimana jenis keamanannya?eval
yang tidak diketik seperti Anda perlu menguji hasilnya untuk melihat apa yang keluar, yang bukan hal baru di Typed Racked (kesepakatan yang sama sebagai fungsi yang mengambil tipe gabunganString
danNumber
). Cara implisit untuk melihat bahwa hal ini dapat dilakukan adalah fakta bahwa Anda dapat menulis dan menggunakan bahasa yang diketik secara dinamis dalam bahasa yang diketik secara statis-HM.Jika yang Anda inginkan hanyalah bahasa yang diketik secara statis yang tampak seperti Lisp, Anda dapat melakukannya dengan mudah, dengan menentukan pohon sintaks abstrak yang mewakili bahasa Anda dan kemudian memetakan AST tersebut ke ekspresi-S. Namun, saya tidak berpikir saya akan menyebut hasilnya Lisp.
Jika Anda menginginkan sesuatu yang benar-benar memiliki karakteristik Lisp-y selain sintaks, dimungkinkan untuk melakukan ini dengan bahasa yang diketik secara statis. Namun, ada banyak karakteristik untuk Lisp yang sulit untuk mendapatkan banyak pengetikan statis berguna. Untuk mengilustrasikannya, mari kita lihat struktur daftar itu sendiri, yang disebut kontra , yang merupakan blok penyusun utama Lisp.
Menyebut kontra daftar, meskipun
(1 2 3)
terlihat seperti satu, adalah sedikit keliru. Misalnya, ini sama sekali tidak dapat dibandingkan dengan daftar yang diketik secara statis, seperti daftar C ++std::list
atau Haskell. Itu adalah daftar tertaut satu dimensi yang semua selnya berjenis sama. Lisp dengan senang hati mengizinkan(1 "abc" #\d 'foo)
. Plus, bahkan jika Anda memperluas daftar yang diketik statis untuk mencakup daftar-daftar, tipe objek ini mengharuskan setiap elemen dari daftar adalah sub-daftar. Bagaimana Anda mewakili((1 2) 3 4)
mereka?Lisp kerucut membentuk pohon biner, dengan daun (atom) dan cabang (kerucut). Selanjutnya, daun dari pohon seperti itu mungkin mengandung semua jenis Lisp atomik (non-kontra)! Fleksibilitas struktur inilah yang membuat Lisp begitu baik dalam menangani komputasi simbolik, AST, dan mengubah kode Lisp itu sendiri!
Jadi bagaimana Anda memodelkan struktur seperti itu dalam bahasa yang diketik secara statis? Mari kita coba di Haskell, yang memiliki sistem tipe statis yang sangat kuat dan tepat:
Masalah pertama Anda adalah cakupan tipe Atom. Jelas, kami belum memilih jenis Atom dengan fleksibilitas yang cukup untuk mencakup semua jenis objek yang ingin kami selempang secara conses. Alih-alih mencoba memperluas struktur data Atom seperti yang tercantum di atas (yang dapat Anda lihat dengan jelas adalah rapuh), katakanlah kami memiliki kelas tipe magis
Atomic
yang membedakan semua tipe yang kami ingin buat menjadi atom. Kemudian kami dapat mencoba:Tetapi ini tidak akan berhasil karena membutuhkan semua atom di pohon memiliki tipe yang sama . Kami ingin mereka dapat berbeda dari daun ke daun. Pendekatan yang lebih baik membutuhkan penggunaan bilangan eksistensial Haskell :
Tapi sekarang Anda sampai pada inti masalahnya. Apa yang dapat Anda lakukan dengan atom dalam struktur seperti ini? Struktur apa yang mereka miliki yang dapat dimodelkan
Atomic a
? Tingkat keamanan tipe apa yang Anda jamin dengan tipe seperti itu? Perhatikan bahwa kami belum menambahkan fungsi apa pun ke kelas tipe kami, dan ada alasan bagus: atom tidak memiliki kesamaan di Lisp. Supertipe mereka di Lisp hanya disebutt
(yaitu top).Untuk menggunakannya, Anda harus menemukan mekanisme untuk secara dinamis memaksa nilai atom menjadi sesuatu yang benar-benar dapat Anda gunakan. Dan pada saat itu, pada dasarnya Anda telah menerapkan subsistem yang diketik secara dinamis dalam bahasa yang Anda ketik secara statis! (Seseorang tidak bisa tidak mencatat kemungkinan akibat wajar dari Aturan Pemrograman Kesepuluh Greenspun .)
Perhatikan bahwa Haskell menyediakan dukungan hanya untuk subsistem dinamis dengan
Obj
tipe, yang digunakan bersama denganDynamic
tipe dan kelas Typeable untuk menggantikanAtomic
kelas kita , yang memungkinkan nilai arbitrer disimpan dengan tipenya, dan paksaan eksplisit kembali dari tipe tersebut. Itulah jenis sistem yang perlu Anda gunakan untuk bekerja dengan struktur kontra Lisp secara umum penuh.Yang juga dapat Anda lakukan adalah pergi ke arah lain, dan menanamkan subsistem yang diketik secara statis dalam bahasa yang diketik secara dinamis. Ini memungkinkan Anda memanfaatkan pemeriksaan tipe statis untuk bagian-bagian program Anda yang dapat memanfaatkan persyaratan tipe yang lebih ketat. Ini tampaknya menjadi pendekatan yang diambil dalam bentuk terbatas CMUCL dari pemeriksaan jenis yang tepat , misalnya.
Terakhir, ada kemungkinan memiliki dua subsistem terpisah, yang diketik secara dinamis dan statis, yang menggunakan pemrograman gaya kontrak untuk membantu menavigasi transisi di antara keduanya. Dengan cara itu bahasa dapat mengakomodasi penggunaan Lisp di mana pemeriksaan tipe statis akan lebih menjadi penghalang daripada bantuan, serta penggunaan di mana pemeriksaan tipe statis akan menguntungkan. Ini adalah pendekatan yang diambil oleh Typed Racket , seperti yang akan Anda lihat dari komentar berikut.
sumber
(Listof Integer)
dan(Listof Any)
. Jelas, Anda akan mencurigai yang terakhir tidak berguna karena Anda tidak tahu apa-apa tentang tipenya, tetapi di TR, Anda nanti dapat menggunakan(if (integer? x) ...)
dan sistem akan tahu bahwa itux
adalah Integer di cabang pertama.dynamic
tipe menjadi populer dalam bahasa statis sebagai semacam solusi untuk mendapatkan beberapa manfaat dari bahasa yang diketik secara dinamis, dengan pertukaran biasa dari nilai-nilai ini dibungkus dengan cara yang membuat tipe dapat diidentifikasi. Tapi di sini raket yang terlalu diketik melakukan pekerjaan yang sangat baik dalam membuatnya nyaman dalam bahasa - pemeriksa tipe menggunakan kemunculan predikat untuk mengetahui lebih banyak tentang jenis. Misalnya, lihat contoh yang diketik di halaman raket dan lihat bagaimanastring?
"mengurangi" daftar string dan angka menjadi daftar string.Jawaban saya, tanpa tingkat kepercayaan yang tinggi mungkin . Jika Anda melihat bahasa seperti SML, misalnya, dan membandingkannya dengan Lisp, inti fungsional masing-masing hampir identik. Akibatnya, Anda tidak akan kesulitan menerapkan beberapa jenis pengetikan statis ke inti Lisp (aplikasi fungsi dan nilai primitif).
Pertanyaan Anda memang mengatakan penuh , dan di mana saya melihat beberapa masalah masuk adalah pendekatan kode-sebagai-data. Jenis ada pada tingkat yang lebih abstrak daripada ekspresi. Lisp tidak memiliki perbedaan ini - semuanya berstruktur "datar". Jika kita menganggap beberapa ekspresi E: T (di mana T adalah representasi dari tipenya), dan kemudian kita menganggap ekspresi ini sebagai data biasa, lalu apa sebenarnya tipe T di sini? Yah, itu sejenis! A kind adalah yang lebih tinggi, tipe pesanan, jadi mari kita lanjutkan dan katakan sesuatu tentang itu di kode kita:
Anda mungkin melihat ke mana saya pergi dengan ini. Saya yakin dengan memisahkan informasi jenis dari kode itu akan mungkin untuk menghindari jenis referensi diri jenis ini, namun itu akan membuat jenis tidak terlalu "cadel" dalam rasa mereka. Mungkin ada banyak cara untuk mengatasi ini, meskipun tidak jelas bagi saya mana yang terbaik.
EDIT: Oh, jadi dengan sedikit googling, saya menemukan Qi , yang tampaknya sangat mirip dengan Lisp kecuali bahwa itu diketik secara statis. Mungkin ini tempat yang baik untuk mulai melihat di mana mereka membuat perubahan untuk mendapatkan pengetikan statis di sana.
sumber
Dylan: Memperluas sistem tipe Dylan untuk inferensi tipe dan deteksi kesalahan yang lebih baik
sumber