Tipe kelas pertama memungkinkan sesuatu yang disebut pengetikan dependen . Ini memungkinkan programmer untuk menggunakan nilai tipe pada level tipe. Misalnya, tipe semua pasangan bilangan bulat adalah tipe biasa, sedangkan pasangan semua bilangan bulat dengan angka kiri lebih kecil dari angka kanan adalah tipe dependen. Contoh pengantar standar dari ini adalah daftar panjang disandikan (biasanya disebut Vector
dalam Haskell / Idris). Kode pseudo berikut adalah campuran dari Idris dan Haskell.
-- a natural number
data Nat = Zero | Successor Nat
data Vector length typ where
Empty : Vector Zero typ
(::) : typ -> Vector length typ -> Vector (Successor length) typ
Bagian kode ini memberi tahu kita dua hal:
- Daftar kosong memiliki panjang nol.
cons
ing elemen ke daftar membuat daftar panjang n + 1
Ini terlihat sangat mirip dengan konsep lain dengan 0 dan n + 1
, bukan? Saya akan kembali ke sana.
Apa yang kita dapat dari ini? Kami sekarang dapat menentukan properti tambahan dari fungsi yang kami gunakan. Misalnya: Properti penting append
adalah bahwa panjang daftar yang dihasilkan adalah jumlah dari panjang dari dua daftar argumen:
plus : Nat -> Nat -> Nat
plus Zero n = n
plus (Successor m) n = Successor (plus m n)
append : Vector n a -> Vector m a -> Vector (plus n m) a
append Empty ys = ys
append (x::xs) ys = x :: append xs ys
Namun secara keseluruhan teknik ini tampaknya tidak semua berguna dalam pemrograman sehari-hari. Bagaimana ini berhubungan dengan soket, POST
/ GET
permintaan dan sebagainya?
Yah itu tidak (setidaknya bukan tanpa usaha yang cukup). Tapi itu bisa membantu kita dengan cara lain:
Tipe dependen memungkinkan kita untuk merumuskan invarian dalam kode - aturan seperti bagaimana suatu fungsi harus berperilaku. Dengan menggunakan ini, kami mendapatkan keamanan tambahan tentang perilaku kode, mirip dengan kondisi sebelum dan sesudah Eiffel. Ini sangat berguna untuk pembuktian teorema otomatis, yang merupakan salah satu kegunaan yang mungkin untuk Idris.
Kembali ke contoh di atas, definisi daftar panjang-dikodekan menyerupai konsep matematika induksi . Di Idris, Anda sebenarnya dapat merumuskan konsep induksi pada daftar seperti berikut:
-- If you can supply the following:
list_induction : (Property : Vector len typ -> Type) -> -- a property to show
(Property Empty) -> -- the base case
((w : a) -> (v : Vector n a) ->
Property v -> Property (w :: v)) -> -- the inductive step
(u : Vector m b) -> -- an arbitrary vector
Property u -- the property holds for all vectors
Teknik ini terbatas pada bukti konstruktif, tetapi tetap sangat kuat. Anda dapat mencoba menulis secara append
induktif sebagai latihan.
Tentu saja, tipe dependen hanyalah satu penggunaan tipe kelas satu, tapi ini bisa dibilang salah satu yang paling umum. Penggunaan tambahan termasuk, misalnya, mengembalikan tipe tertentu dari fungsi berdasarkan argumennya.
type_func : Vector n a -> Type
type_func Empty = Nat
type_func v = Vector (Successor Zero) Nat
f : (v : Vector n a) -> type_func v
f Empty = 0
f vs = length vs :: Empty
Ini adalah contoh yang tidak masuk akal, tetapi ini menunjukkan sesuatu yang tidak dapat Anda tiru tanpa tipe kelas satu.