ไม่มีข้อ จำกัด เลย! เมื่อฉันเริ่มเรียนรู้พื้นฐานหมวดหมู่ - ทฤษฎีสำหรับตัวสร้างแบบพิมพ์จุดนี้ทำให้ฉันสับสนเช่นกัน เราจะไปที่ แต่ก่อนอื่นให้ฉันกำจัดความสับสน คำพูดสองคำนี้:
functor ดังกล่าวสามารถมีได้ตามหมวดหมู่เป้าหมายหมวดหมู่ที่สร้างขึ้นโดยใช้ตัวสร้างประเภท
และ
อาจคิดว่า functors มีหมวดหมู่ใด ๆ ที่เป็นเป้าหมายของ functor เช่นหมวดหมู่ของ Haskell ทุกประเภท
แสดงให้เห็นว่าคุณเข้าใจผิดว่า functor คืออะไร (หรืออย่างน้อยที่สุดคุณกำลังใช้คำศัพท์ในทางที่ผิด)
Functors ไม่สร้างหมวดหมู่ functor เป็นการทำแผนที่ระหว่างหมวดหมู่ Functors นำวัตถุและมอร์ฟิซึ่มส์ (ประเภทและฟังก์ชั่น) ในหมวดหมู่ของแหล่งที่มาเพื่อวัตถุและมอร์ฟิซึ่มส์ในหมวดหมู่เป้าหมาย
โปรดทราบว่านี้หมายถึง functor เป็นจริงคู่ของแมปการทำแผนที่บนวัตถุF_objและการทำแผนที่ใน morphisms F_morph ใน Haskell, ส่วนวัตถุF_objของ functor เป็นชื่อของตัวสร้างประเภท (เช่นList) ในขณะที่ส่วนหนึ่งซึ่มส์เป็นฟังก์ชั่นfmap(มันขึ้นอยู่กับคอมไพเลอร์ Haskell จะสังคายนาซึ่งfmapเราหมายถึงการแสดงออกใดก็ตาม) ดังนั้นเราไม่สามารถพูดได้ว่าListเป็นนักแสดง เพียงการรวมกันของListและfmapเป็นนักแสดง แต่ถึงกระนั้นการใช้คำพูดในทางที่ผิด โปรแกรมเมอร์เรียกListfunctor ในขณะที่หมวดหมู่ทฤษฎีใช้สัญลักษณ์เดียวกันเพื่ออ้างถึงทั้งสองส่วนของ functor
นอกจากนี้ในการเขียนโปรแกรมฟังก์ชั่นเกือบทั้งหมดเป็นendofunctorsนั่นคือหมวดที่มาและเป้าหมายเหมือนกัน - หมวดหมู่ทุกประเภทในภาษาของเรา ขอเรียกนี้หมวดหมู่ประเภท endofunctor Fในประเภทแผนที่ชนิดTประเภทอื่นFTและฟังก์ชั่นT -> Sฟังก์ชั่นอื่นFT -> FS แน่นอนว่าการทำแผนที่นี้ต้องเป็นไปตามกฎหมายนักแสดง
ใช้Listเป็นตัวอย่าง: เรามีตัวสร้างประเภทList : Type -> Typeและฟังก์ชั่นfmap: (a -> b) -> (List a -> List b)ที่รวมกันเป็น functor T
มีจุดสุดท้ายที่ชัดเจนขึ้น การเขียนList intไม่ได้สร้างรายการจำนวนเต็มชนิดใหม่ ประเภทนี้อยู่แล้ว มันเป็นวัตถุที่อยู่ในหมวดหมู่ของเราประเภท List Intเป็นเพียงวิธีในการอ้างถึง
ตอนนี้คุณกำลังสงสัยว่าทำไม functor ไม่สามารถ map ประเภทไปพูดหรือInt Stringแต่มันสามารถ! เพียงแค่มีการใช้ functor ตัวตน สำหรับหมวดหมู่Cนักแสดงตัวตนจะจับคู่วัตถุทุกอย่างเข้ากับตัวเองและมอร์ฟิซึ่มส์กับตัวเอง มันเป็นเรื่องง่ายที่จะตรวจสอบการทำแผนที่นี้เป็นไปตามกฎหมายของนักแสดง ใน Haskell นี่จะเป็นตัวสร้างประเภทid : * -> *ที่แมปทุกประเภทกับตัวมันเอง ยกตัวอย่างเช่นการประเมินid intint
ยิ่งไปกว่านั้นเราสามารถสร้างฟังก์ชั่นคงที่ซึ่งแมปทุกประเภทเป็นประเภทเดียว ตัวอย่างเช่น functor ToInt : * -> *ที่ToInt a = intทุกประเภทaและแมป morphisms ทั้งหมดกับฟังก์ชันจำนวนเต็ม: fmap f = \x -> x