ก่อนอื่น:
Monad ใด ๆ ก็เป็น functor สมัครและ functor สมัครใด ๆ ที่เป็น functor
นี่เป็นความจริงในบริบทของ Haskell แต่ (อ่านApplicative
ว่า "strong lax monoidal functor") ไม่ใช่โดยทั่วไปด้วยเหตุผลเล็กน้อยที่คุณสามารถมีฟังก์ชั่น "applicative" ระหว่างหมวดหมู่ monoidal ต่าง ๆ ในขณะที่ monads (และ comonads) เป็น endofunctors .
นอกจากนี้การระบุApplicative
มีความแข็งแกร่ง functors หละหลวม monoidal เล็กน้อยทำให้เข้าใจผิดเพราะจะปรับชื่อ (และลายเซ็นประเภทของ(<*>)
) ต้อง functor ระหว่างปิดประเภท monoidalซึ่งรักษาทั้งโครงสร้าง monoidalและหอมภายใน นี้ฟังอาจจะเรียกว่า "หละหลวมปิด functor monoidal" ยกเว้นว่า functor ระหว่างประเภทปิด monoidal ที่รักษาทั้งรักษาทรัพย์สินอื่น ๆ ในวิธีที่ชัดเจน เนื่องจากApplicative
อธิบายเฉพาะ endofunctors ในHask ที่รักษาโครงสร้าง monoidal ของ(,)
มันอินสแตนซ์ของมันจะได้รับคุณสมบัติมากมายโดยอัตโนมัติรวมถึงความแข็งแรงของพวกเขาซึ่งทำให้สามารถถูกกำจัดได้
การเชื่อมต่อที่ชัดเจนด้วยMonad
นั้นเป็นสิ่งประดิษฐ์ของข้อ จำกัด โดยนัยในการApplicative
ก่อให้เกิดแง่มุมต่าง ๆ ของโครงสร้างโมโนโมนิคของพวกเขาที่จะเกิดขึ้นพร้อมกันซึ่งเป็นเรื่องบังเอิญที่มีความสุขซึ่งโชคไม่ดีที่ไม่รอด
เช่นเดียวกับ comonad ในหมวดหมู่นี้เป็น monad ในC o Pเป็นoplax monoidal functor C → Dเป็นหละหลวม monoidal functor C o P → D o P แต่คคo หน้า ค→ Dคo หน้า→ Do หน้าHa s ko หน้าไม่ได้ปิดแบบ monoidal และสิ่งApplicative
ที่ไม่รวมแอปพลิเคชันฟังก์ชันจะไม่ได้รับชื่อ อย่างไรก็ตามผลลัพธ์จะไม่น่าสนใจอย่างมาก:
class (Functor f) => CoMonoidal f where
counit :: f () -> ()
cozip :: f (a, b) -> (f a, f b)
เราสามารถจินตนาการถึงความคิดของ "colax Closed functor" ซึ่งจะมีลักษณะมากกว่านี้Applicative
ถ้ามันมีอยู่จริง น่าเสียดายที่ไม่ได้ (ที่ดีที่สุดของความรู้ของฉัน) หมวดหมู่ที่ปิดทั้งหมด: ในH a s kสอดคล้องกับ morphisms b → aในH a s k o pแต่ไม่ได้ทำงานเป็น หอมภายในมี - เพราะลูกศรจะกลับอะไรบางอย่างร่วมฟังก์ชั่นจะต้องแทนซึ่งเราไม่สามารถกำหนดโดยทั่วไปสำหรับH s kHa s ko หน้าnewtype Op b a = Op (a -> b)
Ha s kb → aHa s ko หน้าOp b a
Ha s k
ถ้าเราแค่แกล้งทำเป็นว่า "colax Closed functors" มีไว้สำหรับและทำงานในแบบที่เราต้องการไร้เดียงสาหวังว่าพวกเขาจะเป็นเช่นนั้นHa s kApplicative
class (Functor f) => CoApplicative f where
copure :: f a -> a
coap :: (f a -> f b) -> f (a -> b)
แน่นอนว่าการเพิ่มduplicate :: f a -> f (f a)
เข้าไปcopure
จะสร้าง comonad (โดยถือว่าเป็นที่น่าพอใจ) แต่ไม่มีความสัมพันธ์ที่ชัดเจนระหว่างcoap
--whatever extend :: (f a -> b) -> f a -> f b
มันอาจจะเป็น เปรียบเทียบประเภทมันจะกลายเป็นที่ชัดเจนว่า dualization ที่เกิดขึ้นในรูปแบบที่แตกต่างกัน: โครงสร้างพื้นฐาน comonoidal duplicate
และcozip
มีน้อยจะทำอย่างไรกับแต่ละอื่น ๆ หรือกับcoap
(ซึ่งอาจจะไม่ได้ทำให้รู้สึกอยู่แล้ว) ในขณะที่liftA2 (,)
และเทียบเท่าและสามารถนำมาจาก(<*>)
join
อีกวิธีที่เป็นไปได้ของการทำให้เป็นคู่Applicative
ซึ่งมีน้อยที่จะทำกับ comonads คือการพิจารณาฟังก์ชั่น monoidal contravariant:
class (Contravariant f) => ContraMonoidal f where
contraunit :: f a
contrazip :: f a -> f b -> f (Either a b)
แต่สิ่งนี้จะดำเนินไปในประเด็นเดียวกันกับที่กล่าวข้างต้นนั่นคือไม่ใช่หมวดหมู่ปิด ถ้าเป็นเราจะมีบางชนิดเช่นว่าเราสามารถเขียนฟังก์ชั่นเหมือนและและอื่น ๆ ที่ทำงานจริงตามที่คาดไว้Ha s ko หน้าb <~ a
contracurry :: (Either c b <~ a) -> (c <~ (b <~ a))
contraapply :: b -> Either a (a <~ b)
Ha s kCoApplicative
อย่างไรก็ตามในหมวดหมู่ปิดแบบ monoidal มีอัธยาศัยดีกว่าคุณอาจโชคดีกว่า โดยเฉพาะอย่างยิ่งฉันเชื่อว่าทั้งสองอย่างKleisli (Cont r)
และหมวดหมู่ที่ตรงข้ามนั้นปิดแบบ monoidal ดังนั้นจึงอาจเป็นบริบทที่ดีกว่าในการสำรวจแนวคิดเหล่านี้