Anda dapat menemukan yang berikut di web:
Jenis jenis yang lebih tinggi == jenis konstruktor?
class AClass[T]{...} // For example, class List[T]
Ada yang mengatakan ini adalah jenis jenis yang lebih tinggi, karena abstrak atas jenis yang akan sesuai dengan definisi.
Jenis yang lebih tinggi adalah jenis yang mengambil jenis lain dan membangun tipe baru
Ini juga dikenal sebagai konstruktor tipe . (Misalnya, dalam Pemrograman dalam Scala ).
Jenis lebih tinggi == jenis konstruktor yang mengambil konstruktor tipe sebagai parameter tipe?
Dalam makalah Generics of a Kind , Anda dapat membaca
... jenis yang abstrak di atas jenis yang abstrak di atas jenis ('jenis yang lebih tinggi') ... "
yang menyarankan itu
class XClass[M[T]]{...} // or trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
adalah jenis yang lebih tinggi.
Jadi dengan mengingat hal ini, sulit untuk membedakan antara konstruktor tipe , tipe lebih tinggi dan konstruktor tipe yang menggunakan konstruktor tipe sebagai parameter tipe , oleh karena itu pertanyaan di atas.
Jawaban:
Biarkan saya menebus permulaan dari kebingungan ini dengan melempar dengan beberapa disambiguasi. Saya suka menggunakan analogi ke tingkat nilai untuk menjelaskan ini, karena orang cenderung lebih akrab dengannya.
Nilai konstruktor biasanya disebut "fungsi" atau "metode". "Konstruktor" ini juga dikatakan "polimorfik" (karena mereka dapat digunakan untuk membangun "barang" dengan "bentuk" yang berbeda), atau "abstraksi" (karena mereka abstrak atas apa yang bervariasi antara instantiasi polimorfik yang berbeda).
Dalam konteks abstraksi / polimorfisme, orde pertama mengacu pada "penggunaan tunggal" abstraksi: Anda mengabstraksi suatu tipe sekali, tetapi tipe itu sendiri tidak dapat mengabstraksi apa pun. Java 5 generics adalah first-order.
Interpretasi tingkat pertama dari karakterisasi abstraksi di atas adalah:
Untuk menekankan tidak ada abstraksi yang terlibat (saya kira Anda bisa menyebutnya "zero-order", tetapi saya belum melihat ini digunakan di mana pun), seperti nilai
1
atau tipeString
, kami biasanya mengatakan sesuatu adalah nilai atau tipe yang "tepat".Nilai yang tepat adalah "segera dapat digunakan" dalam arti tidak menunggu argumen (tidak abstrak atas mereka). Anggap saja sebagai nilai yang dapat Anda cetak / periksa dengan mudah (membuat serialisasi suatu fungsi curang!).
Tipe yang tepat adalah tipe yang mengklasifikasikan nilai (termasuk konstruktor nilai), konstruktor tipe tidak mengklasifikasikan nilai apa pun (mereka pertama-tama harus diterapkan pada argumen tipe yang tepat untuk menghasilkan tipe yang tepat). Untuk instantiate suatu tipe, perlu (tetapi tidak cukup) bahwa itu adalah tipe yang tepat. (Mungkin kelas abstrak, atau kelas yang Anda tidak memiliki akses.)
"Orde Tinggi" hanyalah istilah umum yang berarti penggunaan berulang polimorfisme / abstraksi. Ini berarti hal yang sama untuk tipe dan nilai polimorfik. Secara konkret, abstraksi tingkat tinggi mengabstraksi sesuatu yang abstrak atas sesuatu. Untuk jenis, istilah "jenis yang lebih tinggi" adalah versi tujuan khusus dari "tingkat tinggi" yang lebih umum.
Dengan demikian, versi tingkat tinggi dari karakterisasi kita menjadi:
Jadi, "orde yang lebih tinggi" berarti bahwa ketika Anda mengatakan "mengabstraksi lebih dari X", Anda benar-benar bersungguh-sungguh! Yang
X
diabstraksi tidak kehilangan "hak abstraksi" sendiri: ia dapat mengabstraksikan semua yang diinginkan. (Omong-omong, saya menggunakan kata kerja "abstrak" di sini untuk berarti: meninggalkan sesuatu yang tidak penting untuk definisi nilai atau tipe, sehingga dapat bervariasi / disediakan oleh pengguna abstraksi sebagai argumen .)Berikut adalah beberapa contoh (terinspirasi oleh pertanyaan Lutz melalui email) tentang nilai dan jenis yang tepat, tingkat pertama dan tingkat tinggi:
Di mana kelas yang digunakan didefinisikan sebagai:
Untuk menghindari tipuan melalui mendefinisikan kelas, Anda perlu entah bagaimana mengekspresikan fungsi tipe anonim, yang tidak dapat diekspresikan secara langsung di Scala, tetapi Anda dapat menggunakan tipe struktural tanpa terlalu banyak biaya sintaksis (
#λ
gaya - style adalah karena https://stackoverflow.com / users / 160378 / retronym afaik):Di beberapa versi Scala masa depan hipotetis yang mendukung fungsi tipe anonim, Anda bisa mempersingkat baris terakhir dari contoh menjadi:
(Pada catatan pribadi, saya menyesal pernah berbicara tentang "tipe yang lebih baik", mereka hanya tipe! Ketika Anda benar-benar perlu untuk ambigu, saya sarankan mengatakan hal-hal seperti "ketik parameter konstruktor", "tipe anggota konstruktor" , atau "ketik konstruktor alias", untuk menekankan bahwa Anda tidak berbicara tentang tipe yang tepat saja.)
ps: Untuk memperumit masalah lebih lanjut, "polimorfik" bersifat ambigu dengan cara yang berbeda, karena tipe polimorfik kadang-kadang berarti tipe yang dikuantifikasi secara universal, seperti
Forall T, T => T
, yang merupakan tipe yang tepat, karena mengklasifikasikan nilai polimorfik (dalam Scala, nilai ini dapat berupa ditulis sebagai tipe struktural{def apply[T](x: T): T = x}
)sumber
(Jawaban ini adalah upaya untuk menghias jawaban Adriaan Moor dengan beberapa informasi grafis dan historis.)
Jenis yang lebih tinggi adalah bagian dari Scala sejak 2.5.
Sebelum itu Scala, seperti Java sampai sekarang, tidak memungkinkan untuk menggunakan konstruktor tipe ("generik" di Jawa) untuk digunakan sebagai parameter tipe ke konstruktor tipe. misalnya
tidak mungkin.
(Gambar berasal dari Generics of a Kind Kind )
Konsekuensinya adalah, konstruktor tipe tersebut (misalnya
List
) dapat digunakan sama seperti tipe lain dalam posisi parameter tipe konstruktor tipe dan karenanya mereka menjadi tipe kelas pertama sejak Scala 2.5. (Mirip dengan fungsi yang merupakan nilai kelas pertama di Scala).Dalam konteks sistem tipe yang mendukung jenis yang lebih tinggi, kita dapat membedakan jenis yang tepat , jenis suka
Int
atauList[Int]
dari jenis orde pertama sukaList
dan jenis jenis yang lebih tinggi sepertiFunctor
atauMonad
(jenis yang abstrak atas jenis yang abstrak atas jenis).Sistem tipe Java di sisi lain tidak mendukung jenis dan karenanya tidak memiliki jenis "jenis yang lebih tinggi".
Jadi ini harus dilihat dengan latar belakang sistem tipe pendukung.
Dalam kasus Scala, Anda sering melihat contoh konstruktor tipe seperti
dengan judul "Jenis yang lebih tinggi", misalnya dalam Scala untuk programer generik, bagian 4.3
Ini kadang-kadang missleading, karena banyak merujuk
Container
sebagai jenis kinded lebih tinggi dan tidakIterable
, tapi apa yang lebih tepat adalah,sumber
The jenis jenis biasa seperti
Int
danChar
, yang contoh adalah nilai-nilai, adalah*
. Jenis konstruktor tipe unary sukaMaybe
adalah* -> *
; konstruktor tipe biner seperti jenisEither
( kari )* -> * -> *
, dan sebagainya. Anda dapat melihat tipe sukaMaybe
danEither
fungsi tipe-tingkat: mereka mengambil satu atau lebih tipe, dan mengembalikan tipe.Fungsi adalah orde yang lebih tinggi jika memiliki orde lebih besar dari 1, di mana urutannya (secara informal) kedalaman bersarang, di sebelah kiri, panah fungsi:
1 :: Int
chr :: Int -> Char
fix :: (a -> a) -> a
,map :: (a -> b) -> [a] -> [b]
((A -> B) -> C) -> D
(((A -> B) -> C) -> D) -> E
Singkatnya, tipe yang lebih tinggi hanyalah fungsi level-level yang lebih tinggi.
Int :: *
Maybe :: * -> *
Functor :: (* -> *) -> Constraint
—jenis yang lebih tinggi: mengonversi konstruktor tipe unary ke batasan kelas ketiksumber
Functor
menghasilkan tipe yang tepat (well, trait, tetapi ide yang sama)Functor[F[_]]
dari konstruktor tipeF
.(* => *) => (* => *)
dapat diekspresikan dalam Scala? Jika tidak, dalam bahasa apa pun?* ⇒ * ⇒ *
currying sangat membantu. Terima kasih!(* ⇒ *) ⇒ (* ⇒ *)
bisa juga dieja(* ⇒ *) ⇒ * ⇒ *
. Itu bisa diekspresikan dalam Scala likeFoo[F[_], T]
. Ini jenis seperti (di Haskell)newtype Twice f a = Twice (f (f a))
(mis.,Twice Maybe Int
≅Maybe (Maybe Int)
,Twice [] Char
≅[[Char]]
) atau sesuatu yang lebih menarik seperti monad gratisdata Free f a = Pure a | Free (f (Free f a))
.Saya akan mengatakan: Jenis abstrak yang lebih tinggi di atas konstruktor tipe. Misalnya pertimbangkan
Ini
Functor
adalah "jenis yang lebih tinggi" (seperti yang digunakan dalam kertas "Generik dari Jenis yang Lebih Tinggi" ). Ini bukan konstruktor tipe konkret ("orde pertama")List
(yang abstrak hanya tipe yang tepat). Ini abstrak atas semua konstruktor tipe unary ("orde pertama") (seperti dilambangkan denganF[_]
).Atau dengan kata lain: Di Jawa, kami memiliki tipe konstruktor yang jelas (mis.
List<T>
), Tetapi kami tidak memiliki "tipe yang lebih tinggi", karena kami tidak dapat mengabstraksi mereka (mis. Kami tidak dapat menulisFunctor
antarmuka yang didefinisikan di atas - setidaknya tidak secara langsung ).Istilah "polimorfisme orde tinggi (tipe konstruktor)" digunakan untuk menggambarkan sistem yang mendukung "tipe yang lebih tinggi".
sumber
List<T>
di Jawa akan menjadi konstruktor tipe unary karena jelas jenisnya* -> *
. Apa yang hilang dalam jawaban Jon adalah bahwa Anda harus mampu mengabstraksi "semua hal" (dan bukan hanya yang kedua*
seperti di Jawa) untuk menyebutnya jenis yang lebih baik.def succ(x: Int) = x+1
memperkenalkan "konstruktor nilai" (lihat jawaban saya yang lain untuk apa yang saya maksudkan dengan ini)succ
(tidak ada yang akan menyebut nilai ini sebagai succ (x: Int)). Dengan analogi,Functor
apakah tipe (memang yang lebih tinggi) didefinisikan dalam jawaban Anda. Sekali lagi, Anda tidak harus menyebutnya sebagaiFunctor[F[_]]
(apaF
apa?_
Mereka tidak dalam lingkup sayangnya, gula sintaksis untuk existentials muddies air di sini dengan membuat?!F[_]
KependekanF[T forSome {type T}]
)Scala REPL menyediakan
:kind
perintah yangSebagai contoh,
Ini
:help
memberikan definisi yang jelas jadi saya pikir layak mempostingnya di sini secara keseluruhan (Scala 2.13.2)sumber