Di Haskell, functor typeclass Functor didefinisikan sebagai berikut (lihat misalnya Haskell wiki ):
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
Sejauh yang saya mengerti (perbaiki saya jika saya salah), functor seperti hanya dapat memiliki kategori sasaran kategori dibangun menggunakan tipe konstruktor, misalnya []
, Maybe
, dll Di sisi lain, salah satu mungkin berpikir dari functors memiliki setiap kategori sebagai target dari functor, misalnya kategori semua jenis Haskell. Misalnya, Int
bisa menjadi objek dalam kategori target dari functor, bukan hanya Maybe Int
atau [Int]
.
Apa motivasi untuk pembatasan fungsi Haskell ini?
f
sebelah kanan? Dan dalam skenario Anda,f
harus seperti fungsi Haskell normal dan tipe peta ke tipe. Di Haskell, satu-satunya hal yang diizinkan untuk memiliki jenis* -> *
adalah konstruktor tipe. Keluarga tipe lebih umum, tetapi mereka harus selalu diterapkan sepenuhnyaJawaban:
Tidak ada batasan sama sekali! Ketika saya mulai belajar dasar-teori kategori untuk konstruktor tipe, titik ini juga membingungkan saya. Kita akan membahasnya. Tapi pertama-tama, izinkan saya menjernihkan kebingungan. Dua kutipan ini:
dan
tunjukkan bahwa Anda salah memahami apa yang dimaksud dengan functor (atau paling tidak, Anda menyalahgunakan terminologi).
Functors tidak membangun kategori. Functor adalah pemetaan antar kategori. Functors membawa objek dan morfisme (jenis dan fungsi) dalam kategori sumber ke objek dan morfisme dalam kategori target.
Perhatikan bahwa ini berarti functor benar-benar sepasang pemetaan: pemetaan pada objek F_obj dan pemetaan pada morphisms F_morph . Dalam Haskell, bagian objek F_obj dari functor adalah nama konstruktor tipe (misalnya
List
), sedangkan bagian morfisme adalah fungsifmap
(terserah kompilator Haskell untuk memilah mana yangfmap
kita rujuk dalam setiap ekspresi yang diberikan). Jadi, kita tidak bisa mengatakan ituList
adalah functor; hanya kombinasiList
danfmap
fungsi. Namun, orang-orang menyalahgunakan notasi; pemrogram memanggilList
functor, sementara ahli teori kategori menggunakan simbol yang sama untuk merujuk ke kedua bagian dari functor.Lebih jauh lagi, dalam pemrograman, hampir semua functors adalah endofunctors , yaitu kategori sumber dan target adalah sama - kategori semua tipe dalam bahasa kita. Sebut kategori ini Jenis . Endofunctor F pada Tipe memetakan tipe T ke tipe FT lainnya dan fungsi T -> S ke fungsi lain FT -> FS . Pemetaan ini tentu saja harus mematuhi hukum functor.
Menggunakan
List
sebagai contoh: kita memiliki konstruktor tipeList : Type -> Type
, dan fungsifmap: (a -> b) -> (List a -> List b)
, yang bersama-sama membentuk functor. TAda satu poin terakhir untuk dijernihkan. Menulis
List int
tidak membuat daftar bilangan bulat tipe baru. Jenis ini sudah ada . Itu adalah objek dalam Jenis kategori kami .List Int
hanyalah cara untuk merujuknya.Sekarang, Anda bertanya-tanya mengapa functor tidak dapat memetakan tipe, katakan,
Int
atauString
. Tapi, itu bisa! Orang hanya harus menggunakan functor identitas. Untuk kategori C apa saja , functor identitas memetakan setiap objek ke dirinya sendiri dan morfisme untuk dirinya sendiri. Sangat mudah untuk memverifikasi pemetaan ini memenuhi hukum functor. Di Haskell, ini akan menjadi konstruktor tipeid : * -> *
yang memetakan setiap tipe untuk dirinya sendiri. Misalnya,id int
evaluasi keint
.Selain itu, seseorang bahkan dapat membuat functors konstan , yang memetakan semua tipe ke tipe tunggal. Misalnya, functor
ToInt : * -> *
, di manaToInt a = int
untuk semua jenisa
, dan memetakan semua morfisme ke fungsi identitas bilangan bulat:fmap f = \x -> x
sumber
f a
, di manaf
, sejauh yang saya tahu, konstruktor tipe. Dari apa yang saya ingat dari teori kategori, ini pasti semacam representasi kanonik (objek awal dalam kategori kategori? Mungkin saya menyalahgunakan terminologinya.) Bagaimanapun, saya akan membaca jawaban Anda dengan cermat. Terimakasih banyak.[]
dan:
. Saya maksudkan ini dengan representasi kanonik.(_, int)
yang mengambil tipea
ke tipe produk(a, int)
dan fungsif : 'a -> 'b
keg : 'a * int -> 'a * int
tidak induktif.f : 'a -> 'b
keg : 'a * int -> 'b * int
?