अच्छा, fmap
सिर्फ (a -> b) -> f a -> f b
है, यानी हम एक ठोस कार्य के साथ monadic कार्रवाई के परिणाम को बदलना चाहते हैं। ऐसा अंकन के साथ लिखने के लिए आसान है:
fmap f m = do
a <- m
return (f a)
या, लिखा "कच्चे":
fmap f m = m >>= \a -> return (f a)
यह Control.Monad.liftM
के रूप में उपलब्ध है।
pure :: a -> f a
बेशक return
है। (<*>) :: f (a -> b) -> f a -> f b
थोड़ा सा ट्रिकियर है। हमारे पास एक फ़ंक्शन लौटने की क्रिया है, और एक क्रिया इसके तर्क को वापस कर रही है, और हम इसके परिणाम को वापस करने की क्रिया चाहते हैं। में फिर से अंकन कार्य करें:
mf <*> mx = do
f <- mf
x <- mx
return (f x)
या, desugared:
mf <*> mx =
mf >>= \f ->
mx >>= \x ->
return (f x)
टाडा! यह Control.Monad.ap
के रूप में उपलब्ध है, इसलिए इस प्रकार है कि हम किसी भी इकाई M
के लिए Functor
और Applicative
की एक पूरी उदाहरण दे सकते हैं:
instance Functor M where
fmap = liftM
instance Applicative M where
pure = return
(<*>) = ap
आदर्श रूप में, हम Monad
में सीधे इन कार्यान्वयन निर्दिष्ट करने के लिए, बोझ राहत देने के लिए सक्षम होगा प्रत्येक मोनैड के लिए अलग-अलग उदाहरण परिभाषित करने के लिए, जैसे कि this proposal। यदि ऐसा होता है, तो Applicative
Monad
का सुपरक्लास बनाने में कोई वास्तविक बाधा नहीं होगी, क्योंकि यह सुनिश्चित करेगा कि यह किसी भी मौजूदा कोड को तोड़ नहीं देगा। दूसरी तरफ, इसका मतलब यह है कि Functor
और Applicative
को परिभाषित करने में शामिल बॉयलरप्लेट किसी दिए गए Monad
के लिए न्यूनतम है, इसलिए "अच्छा नागरिक" होना आसान है (और ऐसे उदाहरण किसी भी मोनैड के लिए परिभाषित किए जाने चाहिए)।
इस उत्तर में एक महत्वपूर्ण टुकड़ा गुम है: सबूत है कि अगर दिया गया 'मोनाड' उदाहरण 'एम' वास्तव में मोनाड कानूनों को पूरा करता है, तो आप 'एफएमएपी', 'शुद्ध' और '(<*>) के लिए प्रदान की जाने वाली monadic परिभाषाओं को' फंक्टर और आवेदक कानूनों का पालन करें। हास्केल लागू करने वाले सभी प्रकार यह है कि प्रकार जांचते हैं। –