2012-01-24 10 views
9

मैं ऐसा करने की कोशिश कर रहा हूं जो हास्केल में अंधेरे से स्पष्ट होना चाहिए, जो Just [1] और Just [2] से Just [1, 2] पर जा रहा है। हालांकि मुझे कुछ भी ऑनलाइन नहीं मिल रहा है क्योंकि मैं संबंधित लेकिन अनुपयोगी पृष्ठों को ढूंढता रहता हूं। तो, आप इसे कैसे प्राप्त करते हैं?हास्केल में विलय/संलग्न जस्ट्स

उत्तर

15

आप liftA2 (++) उपयोग कर सकते हैं:

liftA2 (++) :: Maybe [a] -> Maybe [a] -> Maybe [a] 

liftA2 सिर्फ एक Applicative में एक द्विआधारी समारोह लिफ्टों। Applicative एस को संदर्भ में मनमाने ढंग से तर्कों के कार्यों को उठाने के लिए डिज़ाइन किया गया था, इसलिए वे इसके लिए बिल्कुल सही हैं। इस मामले में, Applicative हम उपयोग कर रहे हैं Maybe है। यह कैसे काम करता देखने के लिए, हम परिभाषा देख सकते हैं: (a -> b) -> f a -> f b:

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

(<$>) सिर्फ f अंदर एक ऑपरेटिंग को शुद्ध मूल्यों पर किसी भी समारोह लिफ्टों। (यह सिर्फ fmap के लिए एक उपनाम है, यदि आप Functor रों से परिचित हैं।) Maybe के लिए:

_ <$> Nothing = Nothing 
f <$> Just x = Just (f x) 

(<*>) थोड़ा जटिल काम है: यह f अंदर एक मूल्य के f अंदर एक समारोह लागू होता है: f (a -> b) -> f a -> f bMaybe के लिए:

Just f <*> Just x = Just (f x) 
_ <*> _ = Nothing 

तो, (वास्तव में, f <$> x जो Maybe के लिए Just f <*> x है pure f <*> x के रूप में एक ही बात है।) हम liftA2 (++) की परिभाषा का विस्तार कर सकते हैं:

liftA2 (++) a b = (++) <$> a <*> b 

-- expand (<$>) 
liftA2 (++) (Just xs) b = Just (xs ++) <*> b 
liftA2 (++) _ _ = Nothing 

-- expand (<*>) 
liftA2 (++) (Just xs) (Just ys) = Just (xs ++ ys) 
liftA2 (++) _ _ = Nothing 

दरअसल, हम इन ऑपरेटरों का उपयोग किसी भी किसी भी Applicative में तर्कों की संख्या को उठाने के लिए कर सकते हैं, j liftA2 के पैटर्न का पालन करके ust। इसे आवेदक शैली कहा जाता है, और यह idiomatic Haskell कोड में बहुत आम है। a और b पहले से ही चर हैं, तो इस मामले में, यह सीधे (++) <$> a <*> b लिखकर इसका उपयोग करने के लिए और अधिक मूर्खतापूर्ण हो सकता है। (दूसरी ओर, यदि आप आंशिक रूप से यह लागू कर रहे हैं - एक उच्च क्रम कार्य करने के लिए इसे पारित करने के कहते हैं, - तो liftA2 (++) बेहतर है।)

हर Monad एक Applicative है, इसलिए यदि आप कभी अपने आप से खोजने की कोशिश एक संदर्भ में एक समारोह "लिफ्ट", Applicative शायद आप जो खोज रहे हैं।

+0

बहुत बढ़िया :) धन्यवाद, आपने मुझे अपने बालों को फाड़ने से बचा लिया है। मान लीजिए कि आप '[2]' और 'बस [3] '->' बस [2, 3] 'के बराबर जानते हैं? :) –

+4

@DeanBarnes: '(2 :) <$> बस [3]' –

+0

शानदार जवाब, धन्यवाद @ehird! यह मूल रूप से अब से मेरा संदर्भ है :) –

3

जबकि @ ehird का जवाब बहुत अच्छा है, मैं रूप में एक noobish समाधान का इस्तेमाल किया है जाएगा:

mergeJust a b = do 
    a' <- a 
    b' <- b 
    return (a' ++ b') 
+2

+1 सरल उपकरण से लैस भी नोबस, इस समस्या को हल कर सकते हैं। आप एक मोनद समझ के रूप में भी लिख सकते हैं: '[ए' ++ बी '| एक '<- ए, बी' <- बी] ' –

3

Just रों की एक सूची का हल का विस्तार करने के लिए, आप इस्तेमाल कर सकते हैं

fmap join $ sequence [Just[1],Just[2],Just[3]] 
-- Just [1,2,3] 
1

चूंकि इसका अन्य समाधानों में उल्लेख नहीं किया गया था, इसलिए मैं इसे यहां कहूंगा। अपने काम को पूरा करने का सबसे आसान तरीका, मेरी राय में, Data.Monoid से <> (या mappend) का उपयोग करना है।

import Data.Monoid 

Just [1,2] <> Just [7,8] == Just [1,2,7,8] 

हालांकि, ध्यान दें कि यह समाधान, ehird के अनुप्रयोगी समाधान के विपरीत, Nothing मूल्यों पर शॉर्ट सर्किट होगा।

Just [1,2] <> Nothing ---> Just [1,2] 
--However 
(++) <$> Just [1,2] <*> Nothing ---> Nothing 
+0

कभी-कभी यह उचित व्यवहार होगा, कभी-कभी नहीं। –

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