क्या एक विधेय फ़ंक्शन के रूप में एक पैटर्न का उपयोग करने का एक सुविधाजनक तरीका है?


10

मैं हाल ही में उन स्थितियों में भाग रहा हूं, जहां मुझे एक अन्य समारोह में एक विधेय समारोह पास करने की आवश्यकता है, और अक्सर मैं जो तर्क ढूंढ रहा हूं, वह अनिवार्य रूप से "क्या यह मूल्य इस पैटर्न से मेल खाता है?"

घोषणाओं, doब्लॉकों और सूची बोध में पैटर्न मिलान को प्राथमिकता दी जाती है, लेकिन ऐसे कई कार्य हैं जो एक विधेय को ले जाते हैं a -> Bool, जहां किसी भी तरह से एक पैटर्न में पास करना बहुत आसान होगा। उदाहरण के लिए, takeWhile, until, find, span, आदि

इस प्रकार अब तक मैं कर रहा हूँ \a -> case a of MyCons _ -> True; otherwise -> False, या एक नामित कार्य को एक ला लिख रहा हूं , let myPred (MyCons _) = True; myPred _ = False inलेकिन वे दोनों बहुत बदसूरत लगते हैं और बहुत मुहावरेदार नहीं हैं। "स्पष्ट" (और गलत) तरीका कुछ ऐसा होगा \(MyCons _) -> Trueलेकिन यह आंशिक रूप से, स्वाभाविक रूप से होने के लिए एक त्रुटि फेंकता है, और तब भी ऐसा लगता है कि एक क्लीनर तरीका होना चाहिए।

क्या इस तरह की चीज़ करने के लिए अधिक रसीला / साफ तरीका है? या मैं पूरी तरह से गलत तरीके से चीजों के बारे में जा रहा हूं?


1
हो सकता है कि यह एक "व्यक्तिगत स्वाद" वाली बात हो, लेकिन, यदि आपको केवल एक ही स्थान पर इस चीज़ की ज़रूरत है, तो मैं आपके द्वारा letनापसंद किए जाने वाले क्लॉज़ से काफी खुश होऊंगा - हालाँकि मैं समकक्ष whereक्लॉज़ को पसंद करता हूँ ताकि यह मुख्य परिभाषा को अव्यवस्थित न करे। बेशक, यदि आपको इस उपयोगिता की आवश्यकता एक से अधिक बार समाप्त हो जाती है, तो आप इसे शीर्ष स्तर के कार्य के रूप में परिभाषित करेंगे।
रोबिन जिगमंड

यह निश्चित रूप से ठीक काम करता है। मेरा प्रश्न कुछ हद तक प्रेरित था कि हस्केल आमतौर पर कितना प्रभावशाली है। आमतौर पर ऐसा लगता है कि मुहावरेदार हास्केल में विचारों का दोहराव बहुत कम है, और यह कम से कम प्रभावित करता है। तो यह भी जरूरी नहीं है कि मुझे लगता है कि let myPred...शैली खराब है , लेकिन यह बहुत अधिक क्रियात्मक लगता है जितना कि मैं एक बहुत ही सरल विचार की उम्मीद करूंगा, जो मुझे आश्चर्यचकित करता है कि क्या मैं गलत पेड़ को काट रहा हूं।
डेविड सैम्पसन 23

2
आप चश्मे (लेंस से) पर एक नज़र डाल सकते हैं। वे प्रथम श्रेणी के
कम्पोजिटेबल

1
मुझे लगता है कि हमें इस प्रकार के उदाहरण देखने की आवश्यकता होगी जहां आप इस प्रकार के उच्च-क्रम फ़ंक्शन का उपयोग कर रहे हैं। मेरे हिस्से का कहना है कि समस्या उस डिजाइन के साथ है जिसे पहले स्थान पर इस तरह के विधेय की आवश्यकता होती है।
Chepner

Haskell98 तरीका, इसके लिए, आपके डेटा प्रकार के लिए केस-मैचिंग (डिकंस्ट्रक्टिंग) फ़ंक्शन को परिभाषित करना है, जैसे maybe :: b -> (a -> b) -> Maybe a -> bऔर bool :: a -> a -> Bool -> aफिर, इसे बूलियन-उत्पादक फ़ंक्शन (एस) के साथ तर्क (ओं) के रूप में उपयोग करें। जैसे myCons z f (MyCons x) = f x ; myCons z f _ = z, फिर फोन करना myCons False (const True) aMyConsValue। यह लगभग वही है जो आपने लिखा है, इसमें कार्यात्मक तर्क (ओं) के माध्यम से "अप्रत्यक्ष" / "अमूर्त" का एक और स्तर है।
विल नेस

जवाबों:


7

आप भाषा एक्सटेंशन लैंबडाकेस का उपयोग कर सकते हैं \case MyCons _ -> True; _ -> False, हालांकि यह कई पात्रों को नहीं बचाता है।

मेरा मानना है कि आप कार्यों की एक श्रृंखला लिख सकता है constructedWith :: (Generic a) => (b -> a) -> a -> Bool, constructedWith2 :: (Generic a) => (b -> c -> a) -> a -> Bool, लेकिन मैं कुछ ही घंटों बातें परीक्षण के बिना इसे लागू करने के जेनेरिक्स के साथ सक्षम पर्याप्त नहीं हूँ। मैं यह कोशिश करूंगा, और अपने जवाब को संपादित कर सकता हूं अगर मैं इसे समझ सकता हूं, या यदि यह एक मृत अंत है।

संपादित करें: हाँ, आप यह कर सकते हैं! यहां मेरे कोड का लिंक दिया गया है, जो इसे स्क्रैच से लागू करता है:

https://repl.it/@lalaithion/ConstructedWith

हालाँकि, जेनेरिक कोड प्लंबिंग के लिए http://hackage.haskell.org/package/generic-deriving-1.13.1/docs/Generics-Deriving-ConNames.html जैसे कुछ का उपयोग करना बेहतर हो सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.