Arend - bahasa tipe dependen berbasis HoTT (bagian 1)

Dalam posting ini, kita akan berbicara tentang bahasa JetBrains yang baru dirilis dengan tipe dependen Arend (bahasa ini dinamai Gating Rent ). Bahasa ini telah dikembangkan oleh JetBrains Research selama beberapa tahun terakhir. Dan meskipun repositori setahun yang lalu diposting secara publik di github.com/JetBrains , rilis penuh Arend hanya terjadi pada bulan Juli tahun ini.

Kami akan mencoba memberi tahu bagaimana Arend berbeda dari sistem matematika formal yang ada berdasarkan tipe dependen, dan fungsi apa yang sekarang tersedia untuk penggunanya. Kami berasumsi bahwa pembaca artikel ini umumnya akrab dengan tipe dependen dan telah mendengar setidaknya satu bahasa berdasarkan tipe dependen: Agda, Idris, Coq, atau Lean. Namun, kami tidak berharap pembaca memiliki tipe dependen pada level lanjutan.

Untuk kesederhanaan dan konkret, cerita kami tentang tipe Arend dan homotopy akan disertai dengan implementasi pada Arend dari algoritma pengurutan daftar paling sederhana - bahkan dengan contoh ini Anda dapat merasakan perbedaan antara Arend dan Agda dan Coq. Sudah ada sejumlah artikel tentang Habré yang ditujukan untuk tipe-tipe dependen. Katakanlah tentang implementasi daftar penyortiran menggunakan metode QuickSort di Agda ada artikel seperti itu . Kami akan menerapkan algoritma yang lebih sederhana untuk menyortir sisipan. Dalam hal ini, kami akan fokus pada konstruksi bahasa Arend, dan bukan pada algoritma penyortiran itu sendiri.

Jadi, perbedaan utama antara Arend dan bahasa lain dengan tipe dependen adalah teori logis yang menjadi dasarnya. Arend menggunakan teori jenis homotopy V. Voevodsky yang baru-baru ini ditemukan ( HoTT ). Lebih khusus lagi, Arend didasarkan pada variasi HoTT yang disebut "teori tipe dengan spasi." Ingat bahwa Coq didasarkan pada apa yang disebut kalkulus konstruksi induktif (Kalkulus Konstruksi Induktif), sedangkan Agda dan Idris didasarkan pada teori tipe intensifikasi Martin-Löf . Fakta bahwa Arend didasarkan pada HoTT secara signifikan memengaruhi konstruksi sintaksisnya dan pengoperasian algoritma pengecekan tipe (typcheker). Kami akan membahas fitur-fitur ini dalam artikel ini.

Mari kita coba menggambarkan secara singkat keadaan infrastruktur bahasa. Untuk Arend ada plugin untuk IntelliJ IDEA, yang dapat diinstal langsung dari repositori plugin IDEA. Pada prinsipnya, menginstal plugin cukup untuk sepenuhnya berfungsi dengan Arend, Anda masih tidak perlu mengunduh dan menginstal apa pun. Selain memeriksa jenis, plugin Arend menyediakan fungsionalitas yang akrab bagi pengguna IDEA: ada penyorotan dan penyelarasan kode, berbagai refactor dan tips. Ada juga opsi untuk menggunakan versi konsol Arend. Penjelasan lebih rinci tentang proses instalasi dapat ditemukan di sini .

Contoh kode dalam artikel ini didasarkan pada pustaka standar Arend, jadi kami sarankan mengunduh kode sumbernya dari repositori . Setelah mengunduh, direktori sumber harus diimpor sebagai proyek IDEA menggunakan perintah Impor Proyek. Di Arend, beberapa bagian dari teori tipe homotopy dan teori cincin telah diformalkan. Sebagai contoh, di perpustakaan standar ada implementasi dari cincin bilangan rasional Q bersama dengan bukti dari semua sifat teori-cincin yang diperlukan.

Dokumentasi bahasa terperinci, di mana banyak poin yang dibahas dalam artikel ini dijelaskan lebih terinci, juga ada dalam domain publik. Anda dapat langsung mengajukan pertanyaan kepada Arend pengembang di saluran telegram .

1. Ikhtisar HoTT / Arend


Teori tipe homotopy (atau, singkatnya, HoTT) adalah jenis teori tipe intensional yang berbeda dari teori tipe Martin-Lof klasik (MLTT, yang menjadi dasar Agda) dan kalkulus konstruksi induktif (CIC, yang menjadi dasar Coq), dalam hal itu, bersama dengan pernyataan dan set berisi apa yang disebut jenis tingkat homotopy yang lebih tinggi.

Dalam artikel ini, kami tidak menetapkan tujuan untuk menjelaskan dasar-dasar HoTT secara detail - untuk penjelasan terperinci tentang teori ini, perlu untuk menceritakan kembali seluruh buku (lihat posting ini ). Kami hanya mencatat bahwa teori yang didasarkan pada aksioma HoTT, dalam arti tertentu, jauh lebih elegan dan menarik daripada teori tipe klasik Martin-Löf. Dengan demikian, sejumlah aksioma yang sebelumnya harus dipostulatkan tambahan (misalnya, ekstensionalitas fungsional) dibuktikan dalam HoTT sebagai teorema. Selain itu, di HoTT, seseorang dapat secara internal mendefinisikan bola homotopy multidimensi dan bahkan menghitung beberapa kelompok homotopy mereka.

Namun, aspek-aspek HoTT ini terutama menarik bagi matematikawan, dan tujuan dari artikel ini adalah untuk menjelaskan bagaimana Arend berbasis HoTT dibandingkan dengan Agda / MLTT dan Coq / CIC dengan contoh mewakili yang sederhana dan akrab bagi entitas pemrogram seperti daftar pesanan. Saat membaca artikel ini, cukup untuk memperlakukan HoTT sebagai semacam teori tipe intensional dengan aksioma yang lebih maju, yang memberikan kenyamanan ketika bekerja dengan alam semesta dan persamaan.

1.1 Jenis ketergantungan, korespondensi Curry - Howard, semesta


Ingatlah bahwa bahasa dengan tipe dependen berbeda dari bahasa pemrograman fungsional biasa selain tipe data biasa, seperti daftar atau angka alami, ada beberapa tipe yang bergantung pada nilai parameter. Contoh paling sederhana dari jenis tersebut adalah vektor dengan panjang tertentu n atau pohon seimbang dengan kedalaman tertentu d. Beberapa contoh lebih lanjut dari jenis-jenis tersebut disebutkan di sini.

Ingat bahwa korespondensi Curry - Howard memungkinkan seseorang untuk menafsirkan pernyataan logika sebagai tipe dependen. Gagasan utama dari korespondensi ini adalah bahwa tipe kosong sesuai dengan pernyataan salah, dan tipe populasi sesuai dengan pernyataan yang benar. Jenis elemen dapat dianggap sebagai bukti dari pernyataan logis yang sesuai. Sebagai contoh, setiap elemen seperti bilangan bulat dapat dianggap sebagai bukti dari fakta bahwa bilangan bulat ada (yaitu, jenis bilangan bulat diisi).

Konstruksi alami yang berbeda untuk tipe sesuai dengan koneksi logis yang berbeda:

  • Produk tipe A × B kadang-kadang disebut tipe pasangan Pair A B. Karena tipe ini terisi jika dan hanya jika kedua tipe A dan B terisi, konstruksi ini sesuai dengan "dan" logis.
  • Jumlah tipe A + B. Dalam Haskell, tipe ini disebut E A. Karena tipe ini terisi jika dan hanya jika salah satu tipe A atau B terisi, konstruksi ini sesuai dengan "atau" yang logis.
  • Tipe fungsional A → B. Setiap fungsi dari tipe ini mengubah elemen A ke elemen B. Dengan demikian, fungsi seperti itu ada tepat ketika keberadaan elemen tipe A menyiratkan keberadaan elemen tipe B. Oleh karena itu, konstruksi ini sesuai dengan implikasi.

Misalkan sekarang kita diberi tipe A tertentu dan keluarga tipe B yang diparameterisasi oleh elemen a dari tipe A. Mari kita berikan contoh konstruksi yang lebih kompleks daripada tipe dependen.

  • Jenis fungsi dependen Π (a: A) (B a). Tipe ini bertepatan dengan tipe fungsional A → B yang biasa jika B tidak bergantung pada A. Fungsi tipe Π (a: A) (B a) mengubah elemen apa pun dari tipe A menjadi elemen tipe B a. Jadi, fungsi semacam itu ada jika dan hanya jika, untuk a : A, ada elemen B a. Oleh karena itu, konstruksi ini sesuai dengan kuantifier universal ∀. Untuk tipe fungsional dependen, Arend menggunakan sintaks \Pi (x : A) -> B a , dan istilah yang mendiami tipe ini dapat dikonstruksikan menggunakan ekspresi lambda \lam (a : A) => f a.
  • Jenis pasangan tergantung adalah Σ (a: A) (B a). Tipe ini bertepatan dengan tipe pasangan A × B yang biasa jika B tidak bergantung pada A. Tipe Σ (a: A) (B a) terisi persis ketika ada elemen a: A dan elemen tipe B a. Jadi, tipe ini sesuai dengan quantifier keberadaan . Jenis pasangan dependen dalam Arend dilambangkan dengan \Sigma (a : A) (B a) , dan istilah yang mendiami itu dibangun menggunakan konstruktor dari pasangan (tergantung) (a, b) .
  • Jenis kesetaraan adalah a = a ', di mana a dan' adalah dua elemen dari beberapa jenis A. Jenis tersebut dihuni jika a dan a 'sama, dan kosong sebaliknya. Jelas, tipe ini adalah analog dari predikat kesetaraan dalam logika.

Pada titik ini, kami merujuk pembaca ke sumber di mana korespondensi Curry - Howard dibahas secara lebih rinci (lihat, misalnya, kursus kuliah atau artikel di sini atau di sini ).

Semua ekspresi yang dipertimbangkan dalam teori tipe harus memiliki beberapa tipe. Karena ekspresi yang menunjukkan tipe juga dipertimbangkan dalam kerangka teori ini, mereka juga perlu diberi tipe tertentu. Pertanyaannya adalah, seperti apa jenisnya?

Keputusan naif pertama yang muncul di pikiran adalah untuk menetapkan semua tipe tipe formal \Type , yang disebut alam semesta (disebut demikian karena berisi semua tipe pada umumnya). Jika kita menggunakan alam semesta ini, jumlah konstruksi dan jenis produk yang disebutkan di atas akan menerima tanda tangan \Type → \Type → \Type , dan konstruksi yang lebih kompleks dari produk tergantung dan jumlah bergantung akan menerima tanda tangan Π (A : \Type) → ((A → \Type) → \Type) .

Pada titik ini, muncul pertanyaan, tipe apa yang seharusnya dimiliki oleh \Type semesta itu sendiri? Upaya naif untuk mengatakan bahwa jenis alam semesta \Type , menurut definisi, adalah \Type itu sendiri mengarah ke paradoks Girard , jadi alih-alih sebuah alam semesta tunggal \Type mempertimbangkan hierarki alam semesta yang tak terbatas, mis. rantai bersarang alam semesta \Type 1 < \Type 2 < … , yang levelnya diberi nomor oleh bilangan alami, dan tipe alam semesta \Type i , menurut definisi, adalah alam semesta \Type (i+1) . Untuk jenis konstruksi yang disebutkan di atas, tanda tangan yang lebih kompleks juga harus diperkenalkan.

Dengan demikian, alam semesta dalam teori tipe diperlukan sehingga setiap ekspresi memiliki tipe tertentu. Dalam beberapa varietas teori tipe, alam semesta digunakan untuk tujuan lain: untuk membedakan antara varietas jenis. Kita telah melihat bahwa set dan pernyataan adalah tipe kasus khusus. Ini menunjukkan bahwa masuk akal untuk memperkenalkan ke dalam teori Prop universe yang terpisah untuk pernyataan dan hierarki yang terpisah dari alam semesta Set i . Ini persis pendekatan yang digunakan dalam Kalkulus Konstruksi Induktif, teori di mana sistem Coq didasarkan.

1.2 Contoh tipe induktif paling sederhana dan fungsi rekursif


Pertimbangkan definisi Arend dari tipe data induktif yang paling sederhana: tipe Boolean, tipe angka alami, dan daftar polimorfik. Arend menggunakan \data kata kunci untuk memperkenalkan tipe induktif baru.

\data Empty -- ,

\data Bool
| true
| false

\data Nat
| zero
| suc Nat

\data List (A : \Set)
| nil
| \infixr 5 :-: A (List A)


Seperti yang Anda lihat dari contoh di atas, setelah \data kata kunci, Anda perlu menentukan nama tipe induktif dan daftar konstruktornya. Pada saat yang sama, tipe data dan konstruktor mungkin memiliki beberapa parameter. Katakanlah dalam contoh di atas tipe List memiliki satu parameter A Konstruktor daftar nil tidak memiliki parameter, dan konstruktor: -: memiliki dua parameter (salah satunya adalah tipe A , dan yang lainnya adalah tipe List A ). The Univers \Set terdiri dari tipe-tipe yang merupakan set (definisi dari set akan diberikan pada bagian selanjutnya). \infixr memungkinkan Anda untuk menggunakan notasi infiks untuk konstruktor: -: dan, selain itu, memberi tahu parser Arend bahwa operator: -: adalah operasi asosiatif-kanan dengan prioritas 5.

Di Arend, semua kata kunci dimulai dengan karakter garis miring terbalik (“\”), sebuah implementasi yang terinspirasi oleh LaTeX. Perhatikan bahwa aturan leksikal di Arend sangat liberal: Circle_HSpace, contrFibers=>Equiv, suc/=0, zro_*-left dan bahkan n:Nat - semua literal ini adalah contoh pengidentifikasi yang valid di Arend. Contoh terakhir menunjukkan betapa pentingnya bagi pengguna Arend untuk mengingat untuk menempatkan spasi antara pengidentifikasi dan karakter titik dua . Perhatikan bahwa dalam pengidentifikasi Arend tidak diperbolehkan untuk menggunakan karakter Unicode (khususnya, Anda tidak dapat menggunakan Cyrillic).

Arend menggunakan kata kunci \func untuk mendefinisikan fungsi. Sintaks dari konstruksi ini adalah sebagai berikut: setelah kata kunci \func , Anda perlu menentukan nama fungsi, parameternya dan jenis nilai kembali. Elemen terakhir dalam mendefinisikan suatu fungsi adalah tubuhnya.

Jika dimungkinkan untuk secara eksplisit menentukan ekspresi di mana fungsi yang diberikan dihitung, maka untuk menunjukkan tubuh fungsi, token => digunakan. Pertimbangkan, misalnya, definisi fungsi negasi jenis.

 \func Not (A : \Type) : \Type => A -> Empty 

Tipe kembalinya suatu fungsi tidak selalu harus ditentukan secara eksplisit. Pada contoh di atas, Arend akan dapat secara independen menyimpulkan tipe Not , dan kita dapat menghilangkan ungkapan ": \Type " setelah tanda kurung.

Seperti dalam kebanyakan sistem matematika yang diformalkan, pengguna tidak harus menentukan tingkat prediktif eksplisit untuk \Type semesta, dan definisi di mana alam semesta digunakan tanpa secara eksplisit menentukan tingkat prediksi dianggap polimorfik .

Sekarang mari kita coba mendefinisikan fungsi yang menghitung panjang daftar. Fungsi seperti itu mudah diidentifikasi melalui pencocokan pola. Arend menggunakan \elim kata kunci untuk ini. Setelah itu, Anda harus menentukan variabel tempat perbandingan dilakukan (jika ada lebih dari satu variabel seperti itu, maka mereka harus ditulis dengan koma). Jika perbandingan dilakukan untuk semua parameter eksplisit, maka \elim beserta variabel dapat dihilangkan. Ini diikuti oleh blok titik perbandingan, dipisahkan satu sama lain oleh bilah vertikal "|". Setiap item dalam blok ini adalah ekspresi dari bentuk «, » => «» .

 \func length {A : \Set} (l : List A) : Nat | nil => 0 | :-: x xs => suc (length xs) 

Pada contoh di atas, parameter A dari fungsi length dikelilingi oleh kurung kurawal. Tanda kurung di Arend ini digunakan untuk menunjukkan argumen implisit, mis. argumen yang dapat dihilangkan pengguna saat memanggil suatu fungsi atau menggunakan tipe. Perhatikan bahwa di Arend Anda tidak dapat menggunakan notasi infiks untuk menunjuk konstruktor saat mencocokkan dengan pola, sehingga notasi awalan digunakan dalam contoh sampel.

Seperti dalam Coq / Agda, dalam Arend semua fungsi harus dijamin akan selesai (mis., Pemeriksaan penghentian hadir di Arend). Dalam definisi fungsi panjang, pemeriksaan ini berhasil, karena panggilan rekursif secara ketat mengurangi argumen eksplisit pertama. Jika pengurangan seperti itu tidak terjadi, Arend akan memberikan pesan kesalahan.

 \func bad : Nat => bad [ERROR] Termination check failed for function 'bad' In: bad 

Arend memungkinkan dependensi melingkar dan fungsi saling rekursif yang pemeriksaan kelengkapannya juga dilakukan. Algoritma pemeriksaan ini dilaksanakan berdasarkan artikel oleh A. Abel. Di dalamnya Anda akan menemukan deskripsi yang lebih rinci tentang kondisi yang harus dipenuhi fungsi rekursif bersama.

1.3 Apa perbedaan set dari pernyataan?


Kami sebelumnya menulis bahwa contoh tipe adalah himpunan dan pernyataan. Selain itu, kami menggunakan kata kunci \Type dan \Set untuk menunjukkan semesta di Arend. Pada bagian ini, kami akan mencoba menjelaskan secara lebih rinci bagaimana pernyataan berbeda dari set dalam hal varietas dari teori tipe intensional (MLTT, CIC, HoTT), dan pada saat yang sama menjelaskan apa arti dari kata kunci \Prop , \Set dan \Type dalam Arend terdiri.

Ingatlah bahwa dalam teori klasik Martin-Lof tidak ada pemisahan tipe menjadi himpunan dan pernyataan. Secara khusus, dalam teori hanya ada satu kumulatif alam semesta (yang dilambangkan dengan Set in Agda, atau Type in Idris, atau Sort in Lean). Pendekatan ini adalah yang paling sederhana, tetapi ada situasi di mana kekurangannya terwujud. Misalkan kita sedang berusaha mengimplementasikan tipe "daftar pesanan" sebagai pasangan tidak tetap yang terdiri dari daftar dan bukti pemesanannya. Ternyata kemudian, dalam kerangka MLTT "murni", tidak akan mungkin untuk membuktikan kesetaraan daftar terurut yang terdiri dari elemen identik, yang pada saat bersamaan berbeda dalam hal bukti pemesanan. Untuk memiliki kesetaraan seperti itu akan sangat alami dan diinginkan, sehingga ketidakmungkinan untuk membuktikannya dapat dianggap sebagai cacat teoritis dalam MLTT.

Di Agda, masalah ini sebagian diselesaikan dengan bantuan yang disebut annotations of immateriality (lihat sumbernya , di mana contoh daftar dibahas lebih rinci). Anotasi ini, bagaimanapun, bukan merupakan konstruk dari teori MLTT, juga bukan merupakan konstruk penuh pada tipe (tidak mungkin untuk menandai dengan anotasi tipe yang tidak digunakan dalam argumen fungsi).

Dalam CIC, berdasarkan CIC, ada dua alam semesta berbeda yang saling bersarang: Prop (alam semesta pernyataan) dan Set (alam semesta himpunan), yang dicelupkan ke dalam hierarki komprehensif semesta Type . Perbedaan utama antara Prop dan Set adalah bahwa ada sejumlah batasan pada variabel yang jenisnya termasuk Prop dalam Coq. Sebagai contoh, mereka tidak dapat digunakan dalam perhitungan, dan perbandingan dengan sampel untuk mereka hanya mungkin dilakukan di dalam bukti pernyataan lain. Di sisi lain, semua elemen dari jenis milik Prop semesta adalah sama dalam aksioma bukti tidak penting, lihat pernyataan di Coq.Logic.ProofIrrelevance . Dengan menggunakan aksioma ini, kita dapat dengan mudah membuktikan kesetaraan dari daftar pesanan yang disebutkan di atas.

Akhirnya, pertimbangkan pendekatan Arend / HoTT untuk pernyataan dan alam semesta. Perbedaan utama adalah bahwa HoTT membuang dengan aksioma bukti tidak penting. Artinya, tidak ada aksioma khusus dalam HoTT yang mendalilkan bahwa semua elemen pernyataan adalah sama. Tetapi dalam HoTT, tipe, menurut definisi , adalah pernyataan jika dapat dibuktikan bahwa semua elemennya sama satu sama lain. Kita dapat mendefinisikan predikat pada tipe yang benar jika tipenya adalah pernyataan:

 \func isProp (A : \Type) => \Pi (aa' : A) -> a = a' 

Muncul pertanyaan: apa jenis yang memenuhi predikat ini, yaitu, pernyataan? Sangat mudah untuk memverifikasi bahwa ini berlaku untuk jenis kosong dan tunggal. Untuk tipe yang paling tidak memiliki dua elemen berbeda, ini tidak lagi benar.

Tentu saja, kami ingin semua penghubung logis yang perlu ditentukan berdasarkan pernyataan. Dalam Bagian 1.1, kita sudah membahas bagaimana mereka dapat ditentukan menggunakan konstruksi tipe-teori. Namun, ada masalah berikut: tidak semua operasi yang kami masukkan mempertahankan properti isProp . Konstruksi produk tipe dan tipe fungsional (tergantung) mempertahankan properti ini, sedangkan konstruksi jumlah tipe dan pasangan dependen tidak. Jadi, kita tidak bisa menggunakan disjungsi dan kuantifikasi keberadaan.

Masalah ini dapat diselesaikan dengan bantuan konstruksi baru, yang ditambahkan ke HoTT, yang disebut pemotongan proposisional . Desain ini memungkinkan Anda untuk mengubah tipe apa pun menjadi pernyataan. Ini dapat dianggap sebagai operasi formal, menyamakan semua istilah yang mendiami tipe ini. Operasi ini agak mirip dengan penjelasan immaterialitas dari Agda, namun, tidak seperti mereka, ini adalah operasi penuh pada jenis dengan tanda tangan \Type -> \Prop .

Contoh pernyataan penting terakhir adalah kesetaraan dua elemen dari beberapa tipe. Ternyata dalam kasus umum jenis kesetaraan a = a' tidak harus berupa pernyataan. Jenis yang disebut satu set:

 \func isSet (A : \Type) => \Pi (aa' : A) -> isProp (a = a') 

Semua jenis yang ditemukan dalam bahasa pemrograman biasa memenuhi predikat ini, yaitu, kesetaraan pada mereka adalah pernyataan. Sebagai contoh, ini berlaku untuk bilangan asli, bilangan bulat, produk set, jumlah set, fungsi lebih dari set, daftar set, dan tipe data induktif lainnya yang dibangun dari set. Ini berarti bahwa jika kita hanya tertarik pada konstruksi yang sudah dikenal seperti itu, maka kita tidak dapat berpikir tentang tipe arbitrer yang tidak memenuhi predikat ini. Semua tipe yang ditemukan dalam Coq adalah set .

Tipe yang tidak disetel menjadi berguna jika Anda ingin berurusan dengan teori tipe homotopy. Untuk saat ini, kami cukup merujuk pembaca ke modul perpustakaan standar yang berisi definisi bola n-dimensi , contoh dari jenis yang bukan kumpulan.

Arend memiliki alam semesta khusus \Prop dan \Set , yang masing-masing terdiri dari pernyataan dan set. Jika kita sudah tahu bahwa tipe A terkandung dalam alam semesta \Prop (atau \Set ), maka bukti properti isProp (atau isSet ) yang sesuai di Arend dapat diperoleh dengan menggunakan aksioma Path.inProp dibangun di awal (kami memberikan contoh menggunakan aksioma ini dalam bagian 2.3).

 \func inProp {A : \Prop} : \Pi (aa' : A) -> a = a' 

Kami telah mencatat bahwa tidak semua konstruksi alami pada tipe mempertahankan properti isProp . Misalnya, tipe data induktif dengan dua atau lebih konstruktor tidak pernah memuaskannya. Seperti disebutkan di atas, kita dapat menggunakan konstruksi pemotongan proposisional yang mengubah tipe apa pun menjadi pernyataan.
Di perpustakaan Arend, implementasi standar pemotongan proposisional disebut Logic.TruncP . Kita bisa mendefinisikan tipe logis "atau" di Arend sebagai memotong jumlah jenis:

 \data \fixr 2 Or (AB : \Type) -- Sum of types; analogue of Coq's type "sum" | inl A | inr B \func \infixr 2 || (AB : \Type) => TruncP (sum AB) -- Logical “or”, analogue of Coq's type "\/" 

Di Arend, ada cara lain, lebih sederhana dan lebih nyaman untuk mendefinisikan tipe induktif yang terpotong proposisi. Untuk melakukan ini, tambahkan saja kata kunci \truncated sebelum mendefinisikan tipe data. Sebagai contoh, definisi logis “atau” di pustaka standar Arend diberikan sebagai berikut.

 \truncated \data \infixr 2 || (AB : \Type) : \Prop -- Logical “or”, analogue of Coq's type "\/" | byLeft A | byRight B 

Pekerjaan lebih lanjut dengan jenis terpotong proposisional menyerupai jenis yang ditugaskan ke alam semesta Prop di Coq. Misalnya, pencocokan pola variabel yang jenisnya adalah pernyataan hanya diizinkan dalam situasi di mana jenis ekspresi itu sendiri merupakan pernyataan. Dengan demikian, selalu mudah untuk mendefinisikan fungsi Or-to-|| melalui perbandingan dengan sampel, tetapi fungsi terbalik untuk itu, hanya jika tipe A `Or` B adalah pernyataan (yang cukup langka, misalnya, ketika tipe A dan B keduanya pernyataan dan saling terpisah satu sama lain).

 \func Or-to-|| {AB : \Prop} (a-or-b : A `Or` B) : A || B | inl a => byLeft a | inr b => byRight 

Ingat juga bahwa kekhasan mekanisme alam semesta dalam Coq adalah bahwa jika beberapa definisi diberikan ke alam semesta Prop , maka sama sekali tidak mungkin untuk menggunakannya dalam perhitungan. Untuk alasan ini, pengembang Coq sendiri tidak merekomendasikan penggunaan konstruksi proposisional, tetapi menyarankan untuk menggantinya dengan analog dari set semesta, jika memungkinkan. Mekanisme alam semesta Arend tidak memiliki kelemahan ini, yaitu, dalam situasi tertentu dimungkinkan untuk menggunakan pernyataan dalam perhitungan. Kami akan memberikan contoh situasi seperti itu ketika kami membahas implementasi algoritma pengurutan daftar.

1.4 Kelas di Arend


Karena tujuan kami adalah menerapkan algoritma penyortiran yang paling sederhana, tampaknya berguna untuk membiasakan diri Anda dengan penerapan set yang dipesan yang tersedia di pustaka standar Arend.

Di Arend, kelas digunakan untuk merangkum operasi dan aksioma yang mendefinisikan struktur matematika, dan juga untuk menyoroti hubungan antara struktur ini menggunakan pewarisan. Kelas juga ruang nama, yang di dalamnya nyaman untuk menempatkan konstruksi dan teori yang sesuai dengan makna.

Kelas dasar dari mana semua kelas pesanan di Arend diwarisi adalah kelas BaseSet , yang tidak mengandung anggota apa pun selain penunjukan E untuk set host (mis., Set di mana BaseSet turunan BaseSet sudah memperkenalkan berbagai operasi). Pertimbangkan definisi kelas ini dari pustaka Arend standar.

 \class BaseSet (E : \Set) -- ,     

Dalam definisi di atas, operator E dinyatakan sebagai parameter kelas. Orang mungkin bertanya, apakah ada perbedaan dalam definisi BaseSet dari definisi berikut, di mana carrier E didefinisikan sebagai bidang kelas?

 \class BaseSet' --      | E : \Set 

Jawaban yang sedikit tidak terduga adalah bahwa dalam Arend tidak ada perbedaan antara dua definisi dalam arti bahwa setiap parameter kelas (bahkan implisit) dalam Arend, pada kenyataannya, adalah bidangnya. Dengan demikian, untuk kedua implementasi BaseSet , orang dapat menggunakan ekspresi xE untuk mengakses bidang E. BaseSet perbedaan antara varian di atas dari definisi BaseSet , tetapi lebih halus, kita akan memeriksanya lebih detail di bagian selanjutnya ketika kita membahas contoh kelas ( instance kelas).

Operasi pengurutan daftar masuk akal hanya jika urutan linier ditentukan pada jenis objek dalam daftar, jadi kami pertama-tama mempertimbangkan definisi dari himpunan sebagian yang dipesan secara ketat dan rangkaian yang dipesan secara linear.

 \class StrictPoset \extends BaseSet { | \infix 4 < : E -> E -> \Prop | <-irreflexive (x : E) : Not (x < x) | <-transitive (xyz : E) : x < y -> y < z -> x < z } \class LinearOrder \extends StrictPoset { | <-comparison (xyz : E) : x < z -> x < y || y < z | <-connectedness (xy : E) : Not (x < y) -> Not (y < x) -> x = y } 

Dari sudut pandang teori tipe, kelas-kelas di Arend dapat dianggap sebagai analog dari tipe sigma dengan sintaksis yang lebih nyaman untuk proyeksi dan konstruktor. , Arend- -, .

, . , . , StrictPoset <-irreflexive <-transitive , E < — . , (, , ) , .

, , . , Arend , , . , . , , , , . :

 \class DecSet \extends BaseSet | decideEq (xy : E) : Dec (x = y) 

Dec , Dec E , E , E , E .

 \data Dec (E : \Prop) | yes E | no (Not E) 

, , Dec ( decidable) Order.LinearOrder . Dec , , , trichotomy , , E , <. , Dec Comparable Java.

 \class Dec \extends LinearOrder, DecSet { | trichotomy (xy : E) : (x = y) || (x < y) || (y < x) | <-comparison xyz x<z => {?} --   | <-connectedness xyx/<yy/<x => {?} | decideEq xy => {?} } 

Dec Dec , , , , . Dec , .

, Dec ( ). Dec , Arend ( Dec LinearOrder, DecSet ), , (diamond inheritance).

: , ( , ).

Dec Order.LinearOrder IDEA ( [Ctrl]+[H]), , .



Arend ( IDEA BaseSet ). , .

1.5 , , .


StrictPoset Nat. Arend , . -, , , - ( ), .

: . .

 data \infix 4 < (ab : Nat) \with | zero, suc _ => zero<suc_ | suc a, suc b => suc<suc (a < b) \lemma irreflexivity (x : Nat) (p : x < x) : Empty | suc a, suc<suc a<a => irreflexivity a a<a \lemma transitivity (xyz : Nat) (p : x < y) (q : y < z) : x < z | zero, suc y', suc z', zero<suc_, suc<suc y'<z' => zero<suc_ | suc x', suc y', suc z', suc<suc x'<y', suc<suc y'<z' => suc<suc (transitivity x' y' z' x'<y' y'<z') 

\func \lemma . , , , . , \lemma , \Prop .

x'<y' — -, x' < y' . - (.. , , ).

(instance) StrictPoset . Arend . \new . « ».

 \func NatOrder => \new StrictPoset { | E => Nat | < => < | <-irreflexive => irreflexivity | <-transitive => transitivity } 

StrictPoset { … } \new : - StrictPoset . - , , , \new . \new C { … } C { … } . C, C. , , NatOrder StrictPoset .

, . , StrictPoset Nat StrictPoset { | E => Nat } . , NatOrder StrictPoset , ( ).

NatOrder \cowith ( - ).

 \func NatOrder : StrictPoset \cowith { | E => Nat | < => < | <-irreflexive => irreflexivity | <-transitive => transitivity } 

, , \instance.

 \instance NatOrder : StrictPoset { | E => Nat | < => < | <-irreflexive => irreflexivity | <-transitive => transitivity } 

Arend , Haskell. NatOrder \instance \cowith , StrictPoset ( ).

, BaseSet - E ( ), , E . .

, Arend . Arend , , ( , « » \classifying \field , Arend ). :

  • Arend . , X StrictPoset , List X List XE .
  • Arend .

, . , \instance StrictPoset , Nat Int ( NatOrder IntOrder ).

, x < y , x, y , , x, y . Arend , NatOrder.< , — IntOrder.< .

, . Arend , < StrictPoset , E. , Arend x<y StrictPoset ( ), E . , < .

, Arend. , \use \coerce . Arend — , , . - , \where .

. fromNat .

 \data Int | pos Nat | neg Nat \with { zero => pos zero } \where { \use \coerce fromNat (n : Nat) => pos n } 

\use \coerce \func , . , , (, , ).

: HoTT JetBrains Research.

Source: https://habr.com/ru/post/id469569/


All Articles