Mengapa funckell Haskell hanya memiliki tipe turunan dalam kategori target mereka?


12

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, Intbisa menjadi objek dalam kategori target dari functor, bukan hanya Maybe Intatau [Int].

Apa motivasi untuk pembatasan fungsi Haskell ini?


4
Kesederhanaan? Haskell tidak memiliki fungsi tipe kelas jadi semua fungsi benar-benar hanya tipe konstruktor.
Daniel Gratzer

2
@ jozefg: Maafkan ketidaktahuan saya: apa itu "fungsi tipe kelas"?
Giorgio

4
Jadi dalam fungsi itu kita berguling-guling di fsebelah kanan? Dan dalam skenario Anda, fharus 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 sepenuhnya
Daniel Gratzer


@ jozefg: Saya sesekali memikirkan pertanyaan ini berulang kali. Saya kira pembatasan Haskell tidak mempengaruhi kekuatan ekspresif dari functors. Sebagai contoh, anggaplah kita memiliki functor yang isomorfis ke functor daftar, tetapi tidak memetakan, katakanlah, Int -> [Int] tetapi Int -> <tipe mewah menggunakan konstruktor tipe tidak>. Maka saya kira orang bisa membuktikan bahwa <fancy type using no type constructor> isomorfik ke [Int]. Jadi memilih objek yang didefinisikan menggunakan konstruktor tipe hanya nyaman dan tidak mengorbankan kekuatan ekspresif.
Giorgio

Jawaban:


1

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:

functor tersebut hanya dapat memiliki kategori target sebagai kategori yang dibangun menggunakan konstruktor tipe

dan

orang mungkin menganggap functors memiliki kategori apa pun sebagai target dari functor, misalnya kategori semua jenis Haskell

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 fungsi fmap(terserah kompilator Haskell untuk memilah mana yang fmapkita rujuk dalam setiap ekspresi yang diberikan). Jadi, kita tidak bisa mengatakan itu Listadalah functor; hanya kombinasi Listdan fmapfungsi. Namun, orang-orang menyalahgunakan notasi; pemrogram memanggil Listfunctor, 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 Listsebagai contoh: kita memiliki konstruktor tipe List : Type -> Type, dan fungsi fmap: (a -> b) -> (List a -> List b), yang bersama-sama membentuk functor. T

Ada satu poin terakhir untuk dijernihkan. Menulis List inttidak membuat daftar bilangan bulat tipe baru. Jenis ini sudah ada . Itu adalah objek dalam Jenis kategori kami . List Inthanyalah cara untuk merujuknya.

Sekarang, Anda bertanya-tanya mengapa functor tidak dapat memetakan tipe, katakan, Intatau String. 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 tipe id : * -> *yang memetakan setiap tipe untuk dirinya sendiri. Misalnya, id intevaluasi ke int.

Selain itu, seseorang bahkan dapat membuat functors konstan , yang memetakan semua tipe ke tipe tunggal. Misalnya, functor ToInt : * -> *, di mana ToInt a = intuntuk semua jenis a, dan memetakan semua morfisme ke fungsi identitas bilangan bulat: fmap f = \x -> x


Terima kasih atas jawaban Anda, pertanyaan ini sudah berusia lebih dari dua tahun. "Functors tidak membangun kategori.": Saya tidak mengatakan itu. Saya mengatakan bahwa functors memetakan dua kategori, di mana kategori target harus memiliki formulir f a, di mana f, 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.
Giorgio

@Giorgio ups, saya tidak melihat berapa umurnya haha. Itu hanya muncul di "pertanyaan yang tidak terjawab". Saya tidak yakin apa yang Anda maksud dengan "representasi kanonik". Sejauh yang saya tahu (dan saya bisa salah di sini), tidak ada hubungan antara functors dan objek awal / terminal.
Gardenhead

Maksud saya ini: en.wikipedia.org/wiki/Initial_algebra (lihat Penggunaan dalam ilmu komputer). Dalam Haskell (sebagian besar) functors didefinisikan pada tipe data aljabar. Objek target dari functor tersebut adalah aljabar awal. Aljabar awal adalah isomorfik ke himpunan istilah yang dibangun menggunakan konstruktor nilai. Misalnya, untuk daftar, []dan :. Saya maksudkan ini dengan representasi kanonik.
Giorgio

Ya, saya tahu apa objek awal itu, dan bahwa tipe data induktif adalah objek awal dalam aljabar F-kategori. Anda benar bahwa banyak tipe-konstruktor didefinisikan secara induktif. Tetapi ini tidak sepenuhnya diperlukan. Misalnya, functor (_, int)yang mengambil tipe ake tipe produk (a, int)dan fungsi f : 'a -> 'bke g : 'a * int -> 'a * inttidak induktif.
Gardenhead

Apakah maksud Anda: "membawa ... fungsi f : 'a -> 'bke g : 'a * int -> 'b * int?
Giorgio
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.