2012-01-19 22 views
17

अक्सर मैं ऐसे पैटर्न के एक समारोह है:हास्केल - पैटर्न वाक्यात्मक चीनी मिलान और जहां

f :: a -> b 
f x = case x of 
    ... -> g ... 
    ... -> g ... 
    ... 
    ... -> g ... 
    where g = ... 

लगभग इस मामले के लिए एक वाक्यात्मक चीनी नहीं है:

f :: a -> b 
f ... = g ... 
f ... = g ... 
... 
f ... = g ... 

दुर्भाग्य से मैं कर सकते हैं ' मुझे where संलग्न करने के लिए संलग्न करें: मुझे स्पष्ट रूप से not in scope एस का गुच्छा मिलेगा। मैं g एक अलग फ़ंक्शन कर सकता हूं, लेकिन यह अच्छा नहीं है: मेरे मॉड्यूल का नामस्थान उपयोगिता कार्यों के साथ प्रदूषित हो जाएगा। क्या कोई कामकाज है?

+4

आप की जरूरत नहीं है निर्यात करने के 'g', इस प्रकार नाम स्थान प्रदूषण केवल एक समस्या * में अपना एकल मॉड्यूल है। * –

उत्तर

10

मुझे लगता है कि आपका पहला उदाहरण बिल्कुल बुरा नहीं है। एकमात्र वाक्य रचनात्मक वजन case x of है, = के बजाय ->; उत्तरार्द्ध इस तथ्य से ऑफसेट है कि आप प्रत्येक खंड के लिए फ़ंक्शन नाम छोड़ सकते हैं। दरअसल, यहां तक ​​कि dflemstr का प्रस्तावित go सहायक फ़ंक्शन सिंटेक्टिक रूप से भारी है।

मान लीजिए, यह सामान्य फ़ंक्शन क्लॉज सिंटैक्स की तुलना में थोड़ा असंगत है, लेकिन यह शायद एक अच्छी बात है: यह अधिक स्पष्ट रूप से उस क्षेत्र को सीमित करता है जिसमें x उपलब्ध है।

+0

परिभाषित कार्यों के लिए समीकरण वाक्यविन्यास एक अनावश्यक चीज की तरह प्रतीत होता है। –

10

नहीं, कोई कामकाज नहीं है। जब आपके पास ऐसे फ़ंक्शन के लिए एकाधिक क्लॉज होते हैं, तो वे where -clause साझा नहीं कर सकते हैं। आप वास्तव में किसी कारण से एक समारोह के फार्म का उपयोग करना चाहते हैं तो ...

f x = 
    go x 
    where 
    go ... = g ... 
    go ... = g ... 
    g = ... 

: अपने ही एकमात्र विकल्प एक मामले बयान उपयोग करें, या कुछ इस तरह करना है।

6
f = g . h -- h is most of your original f 
    where h ... = ... 
     h ... = ... 
     g = 
+0

मुझे लगता है कि ओपी समस्या के सामान्य समाधान की तलाश में था जहां किसी भी समीकरण (या बिल्कुल नहीं) के आरएचएस पर कहीं भी 'जी' दिखाई दे सकता है। –

+1

हाँ, मुझे लगा कि सवाल संदिग्ध था और उस मामले का उत्तर दिया जिसकी पहले से ही उत्तर नहीं दिया गया था। – dave4420

3

आपका मूल समाधान सबसे अच्छा और केवल कामकाज प्रतीत होता है। संवैधानिक रूप से यह हल्का नहीं होने पर फ़ंक्शन पैरामीटर पर सीधे पैटर्न मिलान से कहीं अधिक भारी नहीं है।

लेकिन अगर आपको आवश्यकता है तो बस पूर्व शर्त जांचने के लिए और पैटर्न मिलान नहीं है गार्ड के बारे में मत भूलना, जो आपको where स्कोप को आसानी से एक्सेस करने की अनुमति देता है। लेकिन वास्तव में मैं आपके case of समाधान में कुछ भी बुरा नहीं देखता हूं।

f :: a -> b 
f a 
    | a == 2 = ... 
    | isThree a = ... 
    | a >= 4 = ... 
    | otherwise = ... 
    where isThree x = x == 3 
5
हास्केल 2010 से पर

, या GHC साथ आप भी कर सकते हैं:

f x 
    | m1 <- x = g 
    | m2 <- x = g 
    ... 
    where g = 

लेकिन ध्यान दें कि आप चर g में पैटर्न में बंधे उपयोग नहीं कर सकते। यह के बराबर है:

f x = let g = ... in case() of 
    () -> case x of 
      m1 -> g 
      _ -> case x of 
       m2 -> g 
       .... 
1

यह मान लेना कि आप लगातार सबसे पर g,, मामला बयान की विभिन्न शाखाओं का उपयोग करते हैं तो बिल्कुल भी नहीं सुरक्षित है?

धारणा है कि f :: a -> ba कुछ के लिए और b (संभवतः बहुरूपी), g जरूरी प्रपत्र c -> d, जिसका अर्थ है कि वहाँ एक तरह से लगातार एक a के बाहर एक c निकालने के लिए किया जाना चाहिए के कुछ कार्य है साथ आपरेटिंग। getC :: a -> c पर कॉल करें।उस स्थिति में, समाधान सभी मामलों के लिए h . g . getC का उपयोग करना होगा, जहां h :: d -> b

लेकिन मान लीजिए कि आप ca से हमेशा प्राप्त कर सकते हैं। शायद a फॉर्म f c है, जहां fFunctor है? फिर आप fmap g :: f c -> f d कर सकते हैं, और फिर f d को b में बदल सकते हैं।

बस यहां रैंपिंग की तरह, लेकिन fmap पहली बात थी जब मैंने देखा कि आप प्रत्येक शाखा पर g लागू करने लगते हैं।

0

LambdaCase के साथ, आप भी ऐसा कर सकते हैं:

{-# language LambdaCase #-} 

f :: a -> b 
f = \case 
    ... -> g ... 
    ... -> g ... 
    ... 
    ... -> g ... 
    where g = ... 
संबंधित मुद्दे