2011-03-18 7 views
12

में liftM2 आईडी के रूप में परिभाषित किया गया है, मैं < की परिभाषा को देखा *>, जो एपी, जो बारी में के रूप में परिभाषित किया गया है के रूप में परिभाषित किया जाता है:कैसे और क्यों एपी बेहतर अनुप्रयोगी समझने की कोशिश कर जबकि हास्केल

ap    :: (Monad m) => m (a -> b) -> m a -> m b 
ap    = liftM2 id 

liftM2 और आईडी, अर्थात् के लिए प्रकार हस्ताक्षर को देखते हुए:

liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r 
id      :: a -> a 

मैं समझता हूँ कि कैसे सिर्फ आईडी में पास करके, प्रकार हस्ताक्षर की प्रासंगिकता का (a1 -> a2 -> r) -> m a1 से m (a -> b) को बदलने के लिए लगता है असफल। मुझे यहां क्या समझ नहीं आ रहा है?

+9

शायद वर्तनी 'एपी = liftM2 ($)' अधिक रोशन होगा। इसका मतलब एक ही चीज़ है। – luqui

+8

@luqui: बस उन लोगों के लिए जो नहीं जानते हैं, '($) 'केवल' id' कार्यों के लिए विशिष्ट है। – fuz

उत्तर

17

aid से किसी भी प्रकार पर तत्काल चालू किया जा सकता है, और इस मामले में यह प्रकार a -> b है।

तो हम (a -> b) -> (a -> b) पर id instantiating कर रहे हैं। अब प्रकार चर a1liftM2 से (a -> b) पर instantiated किया जा रहा है, a2a पर instantiated की जा रही है, और rb पर instantiated जा रहा है।

इसे सभी को एक साथ रखकर, liftM2((a -> b) -> (a -> b)) -> m (a -> b) -> m a -> m b, और liftM2 id :: m (a -> b) -> m a -> m b पर तत्काल स्थापित किया गया है।

+0

मुझे क्लिक करने के लिए इसे कुछ बार पढ़ना पड़ा, लेकिन अंततः यह शुरू हो रहा है। जवाब के लिए धन्यवाद। –

2

शीर्ष जवाब निश्चित रूप से सही है और अकेले प्रकार से जल्दी से और कुशलता से काम करता है। एक बार जब आप हास्केल में अच्छे हो जाएं (अस्वीकरण: मैं नहीं हूं) तो यह फ़ंक्शन परिभाषाओं के माध्यम से धीमे होने के बजाय इसे समझने का एक और अधिक प्रभावी तरीका है।

लेकिन चूंकि मुझे हाल ही में 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 होगा, हम जानते हैं कि asomeFunction हो जाएगा और bsomeArgument होगा - उस के लिए क्या bind करता है: यह की निकासी simulates मोनाड संदर्भ मॉड्यूलो का कोई मूल्य किसी भी विशेष प्रसंस्करण जो उस मोनाड के लिए अद्वितीय है।

ताकि अंतिम पंक्ति वास्तव में

return $ f someFunction someArgument 

अब चलो थोड़ा रुकें और याद ap बनाने में हमारा लक्ष्य इकाई संदर्भ के अंदर someArgument पर someFunction कॉल करने के लिए है कि चलो हो जाता है। तो जो भी return उपज का हमारा उपयोग करता है, उसे फ़ंक्शन एप्लिकेशन someFunction someArgument का परिणाम होना चाहिए।

तो हम दो भाव बराबर होना

f someFunction someArgument ==? someFunction someArgument 

ठीक है, तो हम एक समारोह के लिए देख रहे हैं हम x = (someFunction someArgument) जाने f ऐसी है कि

f x = x 

कैसे कर सकते हैं और इसलिए हम जानते हैं कि fid होने की आवश्यकता है।

शुरुआत में वापस जाकर, इसका मतलब है कि हम liftM2 id की तलाश में हैं।

मूल रूप से liftM2 id ma mb कहता है कि मैं अगर a एक समारोह है कि b पर काम कर सकते हैं है m (id a b) ऐसा करने के लिए जा रहा हूँ, तो id जबकि के अंदर परिणाम लौटने "बस उन्हें अकेला छोड़ दें" होगा और a जाने b करने के लिए अपने काम करते हैं, मोनाड संदर्भ।

ऐसा लगता है कि हमने liftM2 को बाईस्टैंडर पूर्वाग्रह के लिए मजबूर कर दिया है।

और आदेश है कि बाहर काम करने के लिए, a क्योंकि ba 'उम्मीद तर्क रों है, एक समारोह प्रकार है कि "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 
संबंधित मुद्दे

 संबंधित मुद्दे