2012-12-14 33 views
5

से लागू फ़ैक्टर और बाएं मैं great good पुस्तक के माध्यम से काम कर रहा हूं, लेकिन मैं आवेदक फंक्शंस के साथ थोड़ा संघर्ष कर रहा हूं।या तो

निम्नलिखित उदाहरण में max दो शायद मज़दूरों की सामग्री पर लागू होता है और Just 6 देता है।

max <$> Just 3 <*> Just 6 

क्यों निम्न उदाहरण में Left "Hello" या तो functors की सामग्री के बजाय लौटा दिया जाता है: Left "Hello World"?

(++) <$> Left "Hello" <*> Left " World" 
+0

यह या तो पारंपरिक उपयोग है कि राइट उस मूल्य का प्रतिनिधित्व करता है जिसमें आप रुचि रखते हैं, जबकि वाम विफलता का प्रतिनिधित्व करता है। दाएं (सही) मानों को आवेदक और फंक्चर का उपयोग करके संयुक्त और संशोधित किया जा सकता है, जबकि एक बाएं से अधिक खराब मूल्य जिद्दी बने रहेंगे, इसलिए यह पहली त्रुटि की रिपोर्ट करने जैसी चीजों के लिए अच्छा है जैसे कि सरल संकलक हो सकता है। – AndrewC

उत्तर

10

क्योंकि Functor उदाहरण (और Applicative आदि) में प्रकार पैरामीटर दूसरे प्रकार पैरामीटर है यह।

Either a b 

में a प्रकार, और Left मूल्यों, functorial या अनुप्रयोगी संचालन से प्रभावित नहीं हैं, क्योंकि वे विफलता मामलों पर विचार कर रहे हैं या अन्यथा दुर्गम।

instance Functor (Either a) where 
    fmap _ (Left x) = Left x 
    fmap f (Right y) = Right (f y) 

उपयोग Right,

(++) <$> Right "Hello" <*> Right " World" 

संयोजन पाने के लिए।

पहले, here's अनुप्रयोगी उदाहरण:

instance Applicative (Either e) where 
    pure    = Right 
    Left e <*> _ = Left e 
    Right f <*> r = fmap f r 

आप देख सकते हैं कि यह 'है लघु

+0

यदि आप प्रकार चर को फ़्लिप करना चाहते हैं, तो आप 'त्रुटियों' पैकेज से 'Data.EitherR' मॉड्यूल का उपयोग कर सकते हैं। यह दो विकल्प प्रदान करता है: 'flipE', जो' या तो 'या' EitherR 'तर्क को फ़्लिप करता है जो इसे एक नए प्रकार में लपेटता है जो चरम क्रम को स्वैप करता है, सममित' फंक्शन 'और' आवेदक 'उदाहरण देता है। –

6

डैनियल उत्कृष्ट जवाब देने के लिए जोड़ने के लिए, वहाँ एक जोड़े को अंक मैं करना चाहते हैं कर रहे हैं सर्किटिंग '- जैसे ही यह Left हिट करता है, यह बंद हो जाता है और बाएं लौटाता है। आप इसे गरीब व्यक्ति के सख्त विश्लेषण के साथ देख सकते हैं:

ghci> (++) <$> Left "Hello" <*> undefined 
Left "Hello"        -- <<== it's not undefined :) !! 

ghci> (++) <$> Right "Hello" <*> undefined 
*** Exception: Prelude.undefined   -- <<== undefined ... :(

ghci> Left "oops" <*> undefined <*> undefined 
Left "oops"        -- <<== :) 

ghci> Right (++) <*> undefined <*> undefined 
*** Exception: Prelude.undefined   -- <<== :( 

दूसरा, आपका उदाहरण थोड़ा मुश्किल है। सामान्य रूप से, Either e में फ़ंक्शन का प्रकार और e संबंधित नहीं है। यहाँ <*> रों प्रकार है:

(<*>) :: Applicative f => f (a -> b) -> f a -> f b 

अगर हम बनाने के प्रतिस्थापन f - >>Either e, हम पाते हैं:

(<*>) :: Either e (a -> b) -> Either e a -> Either e b 

हालांकि अपने उदाहरण में, e और a मैच, सामान्य रूप में वे ऐसा नहीं करेंगी , जिसका अर्थ है कि आप Either e के लिए एक आवेदक उदाहरण को लागू नहीं कर सकते हैं जो बाएं हाथ के तर्क पर फ़ंक्शन लागू करता है।