2011-11-19 11 views
8

से किसी विशिष्ट निर्माता के पहले अवसर को लाने का बेवकूफ तरीका क्या नीचे दिए गए नमूने में स्पष्ट रिकर्सन के बिना किसी सूची में किसी निर्माता की पहली घटना को खोजने का कोई अच्छा तरीका है?सूची

data Elem = A Int | B Char deriving Show 

getA :: [Elem] -> Maybe Elem 
getA [] = Nothing 
getA (e:es) = 
    case e of 
     A a -> Just (A a) 
     _ -> getA es 

उत्तर

11

सीधे शब्दों में

import Data.Maybe (listToMaybe) 
getA xs = listToMaybe [e | [email protected](A _) <- xs] 

परिशिष्ट: और भी बेहतर, भविष्य-रहित एक खाली रिकॉर्ड पद्धति का उपयोग कर (प्रशंसा Hammar):

getA xs = listToMaybe [e | [email protected](A{}) <- xs] 

नोट तथापि, कि यह केवल इसलिए बड़े करीने से बाहर काम करता है रचनाकारों से मेल खाने के लिए। सामान्य गुणों के लिए, find अच्छे है:

get prop xs = listToMaybe [e | e <- xs, prop e] 
get prop xs = listToMaybe (filter prop xs) 
get prop xs = find prop xs 
+0

यह एक अच्छा है, धन्यवाद! – martingw

+0

मुझे सचमुच यह पसंद है कि यह समाधान केवल वांछित डेटा कन्स्ट्रक्टर से अधिक पैटर्न मिलान करने के लिए वर्कअराउंड के लिए सूची समझ का उपयोग कैसे करता है। इसे अपने जवाब में @hammar द्वारा उपयोग किए गए रिक्त रिकॉर्ड पैटर्न का उपयोग करके बेहतर किया जा सकता है। –

+0

@ IonuţG.Stan सहमत हो गया, यह भविष्य के सबूत होगा। –

3

आप पा इस्तेमाल कर सकते हैं:

data Elem = A Int | B Char deriving Show 
getA elements = find (\x->case x of (A _) -> True; _ -> False) elements 
+0

धन्यवाद, बहुत अच्छा! गोल्फ चैंपियन नहीं, हालांकि :-)! – martingw

11

आप Data.List.find उपयोग कर सकते हैं।

getA = find isA 
    where isA (A {}) = True 
     isA _ = False 
+1

'{}' भाग क्या कहा जाता है? मैंने इसे हास्केल में पहले कभी नहीं देखा है। मुझे लगता है कि यह 0 या कई डेटा कन्स्ट्रक्टर फ़ील्ड से मेल खाता है? –

+2

@ IonuţG.Stan: यह कोई फ़ील्ड बाइंडिंग के साथ _record pattern_ है। इसका मतलब यह है कि इससे कोई फर्क नहीं पड़ता कि कन्स्ट्रक्टर के कितने फ़ील्ड हैं, इसलिए यदि आप इसे बदलते हैं, तो आपको इस फ़ंक्शन को बदलने की ज़रूरत नहीं है। – hammar

+0

@hammer धन्यवाद! वास्तव में मैंने सोचा कि यह क्या था। –