शीर्ष जवाब निश्चित रूप से सही है और अकेले प्रकार से जल्दी से और कुशलता से काम करता है। एक बार जब आप हास्केल में अच्छे हो जाएं (अस्वीकरण: मैं नहीं हूं) तो यह फ़ंक्शन परिभाषाओं के माध्यम से धीमे होने के बजाय इसे समझने का एक और अधिक प्रभावी तरीका है।
लेकिन चूंकि मुझे हाल ही में ap
के साथ इस मुद्दे के माध्यम से संघर्ष करना पड़ा था, जबकि मैं The Monad Challenges पर काम कर रहा था, मैंने अपने अनुभव को साझा करने का फैसला किया क्योंकि यह कुछ अतिरिक्त अंतर्ज्ञान प्रदान कर सकता है।
सबसे पहले, जैसे ही मोनाड चुनौतियां पूछती हैं, मैं प्राथमिक मोनाड ऑपरेटर >>=
को संदर्भित करने के लिए bind
नाम का उपयोग करूंगा। मुझे लगता है कि यह बहुत मदद करता है।
हम liftM2
के अपने संस्करण निर्धारित अगर हम ऐसा कर सकते हैं:
liftM2 :: (Monad m) => (a -> b -> c) -> m a -> m b -> m c
liftM2 f ma mb =
ma `bind` \a ->
mb `bind` \b ->
return $ f a b
हम इस का उपयोग करते हुए हमारी मदद करने के ap
बनाना चाहते हैं। आइए एक पल के लिए अकेले फ़ंक्शन f
छोड़ दें और यह सोचें कि यह ap
के रूप में कैसे काम कर सकता है, यह मानते हुए कि हमने f
के लिए सही फ़ंक्शन चुना है।
मान लीजिए कि हम एक समारोह-मान इकाई से ऊपर, ma
भाग पहले भाग के रूप में पारित करने के लिए थे। यह Just (+3)
या [(+3), (*2)]
जैसा कुछ हो सकता है - कुछ "फ़ंक्शन" एक मोनाड संदर्भ के अंदर रह रहे हैं।
और हम दूसरे भाग के रूप में एक तर्क-मान इकाई की आपूर्ति, mb
हिस्सा है, इस तरह के Just 5
या [6,7,8]
के रूप में - कुछ "मूल्य" एक इकाई संदर्भ में जो ma
अंदर रहने वाले समारोह के लिए तर्क के रूप में सेवा कर सकते हैं में रहने वाले।
फिर हम
liftM2 f (m someFunction) (m someArgument) =
(m someFunction) `bind` \a ->
(m someArgument) `bind` \b ->
return $ (f a b)
और लैम्ब्डा कार्यों के अंदर निम्नलिखित bind
होगा, हम जानते हैं कि a
someFunction
हो जाएगा और b
someArgument
होगा - उस के लिए क्या bind
करता है: यह की निकासी simulates मोनाड संदर्भ मॉड्यूलो का कोई मूल्य किसी भी विशेष प्रसंस्करण जो उस मोनाड के लिए अद्वितीय है।
ताकि अंतिम पंक्ति वास्तव में
return $ f someFunction someArgument
अब चलो थोड़ा रुकें और याद ap
बनाने में हमारा लक्ष्य इकाई संदर्भ के अंदर someArgument
पर someFunction
कॉल करने के लिए है कि चलो हो जाता है। तो जो भी return
उपज का हमारा उपयोग करता है, उसे फ़ंक्शन एप्लिकेशन someFunction someArgument
का परिणाम होना चाहिए।
तो हम दो भाव बराबर होना
f someFunction someArgument ==? someFunction someArgument
ठीक है, तो हम एक समारोह के लिए देख रहे हैं हम x = (someFunction someArgument)
जाने f
ऐसी है कि
f x = x
कैसे कर सकते हैं और इसलिए हम जानते हैं कि f
id
होने की आवश्यकता है।
शुरुआत में वापस जाकर, इसका मतलब है कि हम liftM2 id
की तलाश में हैं।
मूल रूप से liftM2 id ma mb
कहता है कि मैं अगर a
एक समारोह है कि b
पर काम कर सकते हैं है m (id a b)
ऐसा करने के लिए जा रहा हूँ, तो id
जबकि के अंदर परिणाम लौटने "बस उन्हें अकेला छोड़ दें" होगा और a
जाने b
करने के लिए अपने काम करते हैं, मोनाड संदर्भ।
ऐसा लगता है कि हमने liftM2
को बाईस्टैंडर पूर्वाग्रह के लिए मजबूर कर दिया है।
और आदेश है कि बाहर काम करने के लिए, a
क्योंकि b
a
'उम्मीद तर्क रों है, एक समारोह प्रकार है कि "TypeOfb" से "SomeReturnType", या TypeOfb -> SomeReturnType
से चला जाता है के लिए होगा में। और निश्चित रूप से b
में TypeOfb
होना चाहिए।
अगर तुम मुझे अंकन में से एक के सेवन, तो की अनुमति देंगे मनमाने ढंग से सिर्फ प्रतीक का उपयोग करते हैं "एक" "TypeOfb" और प्रतीक "बी" "SomeReturnType" के लिए खड़े करने के लिए के लिए खड़े करने के लिए:
`b` --> "a" is its type
`a` --> "a -> b" is its type
फिर ap
के लिए प्रकार हस्ताक्षर होगा
ap :: Monad m => m (TypeOfB -> SomeReturnType) -> m TypeOfB -> m SomeReturnType
==>
ap :: Monad m => m (a -> b) -> m a -> m b
शायद वर्तनी 'एपी = liftM2 ($)' अधिक रोशन होगा। इसका मतलब एक ही चीज़ है। – luqui
@luqui: बस उन लोगों के लिए जो नहीं जानते हैं, '($) 'केवल' id' कार्यों के लिए विशिष्ट है। – fuz