ทำไมฟังก์ชั่นของ Haskell จึงมีประเภทที่ได้รับในหมวดหมู่เป้าหมายเท่านั้น


12

ใน Haskell, functor typeclass functor ถูกกำหนดดังนี้ (ดูตัวอย่างHaskell wiki ):

class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b 

เท่าที่ผมเข้าใจ (โปรดถูกต้องฉันหากฉันผิด) เช่น functor สามารถมีเป้าหมายเป็นหมวดหมู่หมวดหมู่นี้สร้างขึ้นโดยใช้ตัวสร้างประเภทเช่นเพียง[], Maybeฯลฯ บนมืออื่น ๆ หนึ่งอาจคิดว่า functors มีหมวดหมู่ใด ๆ เป็นเป้าหมายของ functor เช่นหมวดหมู่ของ Haskell ทุกประเภท ยกตัวอย่างเช่นIntอาจจะเป็นวัตถุที่อยู่ในหมวดหมู่ที่กำหนดเป้าหมายของ functor หนึ่งไม่เพียงหรือMaybe Int[Int]

แรงจูงใจสำหรับข้อ จำกัด นี้เกี่ยวกับ Haskell functors คืออะไร?


4
ความเรียบง่าย? Haskell ไม่มีฟังก์ชั่นประเภทเฟิร์สคลาสดังนั้นฟังก์ชั่นทั้งหมดเป็นเพียงตัวสร้างประเภท
Daniel Gratzer

2
@jozefg: อภัยความไม่รู้ของฉัน: "ฟังก์ชั่นประเภท First Class" คืออะไร?
จอร์โจ

4
ดังนั้นในฟังก์ชั่นนี้เราจึงเลือกที่fถูกต้อง? และในสถานการณ์ของคุณfควรเป็นเช่นเดียวกับฟังก์ชั่น Haskell ปกติและประเภทแผนที่กับประเภท ใน Haskell สิ่งเดียวที่ได้รับอนุญาตให้มีประเภท* -> *คือประเภทก่อสร้าง ครอบครัวประเภทนั้นมีความทั่วไปมากกว่า แต่พวกเขาจะต้องถูกนำไปใช้อย่างเต็มที่เสมอ
Daniel Gratzer


@jozefg: บางครั้งฉันคิดเกี่ยวกับคำถามนี้ซ้ำแล้วซ้ำอีก ฉันคิดว่าการ จำกัด Haskell จะไม่ส่งผลกระทบต่อพลังการแสดงออกของ functors ตัวอย่างเช่นสมมติว่าเรามี functor ที่ isomorphic กับรายการ functor แต่ไม่แม็พพูด Int -> [Int] แต่ Int -> <ประเภทแฟนซีโดยใช้ตัวสร้างแบบไม่มี> จากนั้นฉันเดาว่าใครสามารถพิสูจน์ได้ว่า <รูปแบบแฟนซีโดยไม่ใช้ตัวสร้างประเภท> คือ isomorphic ถึง [Int] ดังนั้นการเลือกวัตถุที่กำหนดโดยใช้คอนสตรัคเตอร์ชนิดนั้นสะดวกและไม่เสียสละพลังที่แสดงออก
Giorgio

คำตอบ:


1

ไม่มีข้อ จำกัด เลย! เมื่อฉันเริ่มเรียนรู้พื้นฐานหมวดหมู่ - ทฤษฎีสำหรับตัวสร้างแบบพิมพ์จุดนี้ทำให้ฉันสับสนเช่นกัน เราจะไปที่ แต่ก่อนอื่นให้ฉันกำจัดความสับสน คำพูดสองคำนี้:

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


ขอบคุณสำหรับคำตอบของคุณคำถามนี้อายุเกินสองปี "ผู้สร้างไม่ได้สร้างหมวดหมู่": ฉันไม่ได้พูดอย่างนั้น ผมบอกว่า functors ที่แมสองประเภทที่หมวดหมู่เป้าหมายจะต้องมีรูปแบบf aที่fเป็นเท่าที่ผมรู้ว่าตัวสร้างประเภท จากสิ่งที่ฉันจำได้จากทฤษฎีหมวดหมู่สิ่งนี้จะต้องเป็นตัวแทนที่เป็นที่ยอมรับ (วัตถุเริ่มต้นในหมวดหมู่ของหมวดหมู่หรือไม่บางทีฉันอาจใช้คำศัพท์ผิด ๆ ) อย่างไรก็ตามฉันจะอ่านคำตอบของคุณอย่างระมัดระวัง ขอบคุณมาก.
Giorgio

@Giorgio อ๊ะฉันไม่ได้สังเกตว่าอายุเท่าไหร่ฮ่าฮ่า มันเพิ่งปรากฏใน "คำถามที่ไม่มีคำตอบ" ฉันไม่แน่ใจว่าคุณหมายถึงอะไรโดย "การรับรองแบบบัญญัติ" เท่าที่ฉันรู้ (และฉันอาจจะผิดที่นี่) ไม่มีความสัมพันธ์ระหว่าง functors และวัตถุเริ่มต้น / ขั้ว
gardenhead

ฉันหมายถึงสิ่งนี้: en.wikipedia.org/wiki/Initial_algebra (ดูการใช้ในวิทยาการคอมพิวเตอร์) ใน Haskell (ส่วนใหญ่) ฟังก์ชั่นถูกกำหนดไว้ในประเภทข้อมูลเกี่ยวกับพีชคณิต วัตถุเป้าหมายของ functor นั้นเป็นพีชคณิตเริ่มต้น พีชคณิตเริ่มต้นคือ isomorphic กับชุดคำศัพท์ที่สร้างขึ้นโดยใช้ตัวสร้างค่า เช่นสำหรับรายการและ[] :ฉันหมายถึงสิ่งนี้โดยการเป็นตัวแทนที่เป็นที่ยอมรับ
Giorgio

ใช่ฉันรู้ว่าวัตถุเริ่มต้นคืออะไรและประเภทข้อมูลอุปนัยเป็นวัตถุเริ่มต้นในพีชคณิต F ของหมวดหมู่ คุณถูกต้องที่ตัวสร้างชนิดจำนวนมากถูกกำหนด inductively แต่นี่ไม่จำเป็นอย่างเคร่งครัด ตัวอย่างเช่น functor (_, int)ที่ใช้ประเภทaกับประเภทผลิตภัณฑ์(a, int)และฟังก์ชั่นf : 'a -> 'bที่g : 'a * int -> 'a * intจะไม่อุปนัย
gardenhead

คุณหมายถึง: "ใช้ ... ฟังก์ชั่นf : 'a -> 'bเพื่อg : 'a * int -> 'b * int?
Giorgio
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.