हास्केल: टाइपकाॅल बनाम एक फंक्शन पास करना


16

मेरे लिए ऐसा लगता है कि आप हमेशा टाइपकास्ट का उपयोग करने के बजाय फ़ंक्शन तर्क पास कर सकते हैं। उदाहरण के लिए समानता टाइपेकेल को परिभाषित करने के बजाय:

class Eq a where 
  (==)                  :: a -> a -> Bool

और इसका उपयोग अन्य कार्यों में टाइप तर्क को इंगित करने के लिए किया जाना चाहिए Eq:

elem                    :: (Eq a) => a -> [a] -> Bool

क्या हम केवल elemटाइपकाॅल का उपयोग किए बिना अपने फ़ंक्शन को परिभाषित नहीं कर सकते हैं और इसके बजाय एक फ़ंक्शन तर्क पास करते हैं जो काम करता है?


2
जिसे डिक्शनरी कहा जाता है। आप टाइपकास्ट बाधाओं को निहित तर्क के रूप में सोच सकते हैं।
पोसैट

2
आप ऐसा कर सकते हैं, लेकिन यह स्पष्ट रूप से बहुत अधिक सुविधाजनक है कि एक फ़ंक्शन को पारित न करें और बस इसके प्रकार के आधार पर "मानक" का उपयोग करें।
रॉबिन ज़िगमंड

2
आप इसे ऐसे ही डाल सकते हैं, हाँ। लेकिन मेरा तर्क है कि कम से कम एक अन्य महत्वपूर्ण लाभ है: पॉलिमॉर्फिक फ़ंक्शन लिखने की क्षमता जो किसी भी प्रकार पर काम करती है जो एक विशेष "इंटरफ़ेस" या सुविधाओं के सेट को लागू करती है। मुझे लगता है कि टाइपकास्ट बाधाएं बहुत स्पष्ट रूप से व्यक्त करती हैं कि अतिरिक्त फ़ंक्शन तर्क पारित नहीं करता है। विशेष रूप से (दुखद रूप से निहित) "कानून" के कारण, जिसमें कई टाइपकास्टियों को संतुष्ट करना पड़ता है। एक Monad mबाधा मुझे प्रकारों के अतिरिक्त फ़ंक्शन तर्क पारित करने से अधिक कहता है a -> m aऔर m a -> (a -> m b) -> m b
रॉबिन ज़िगमंड


1
TypeApplicationsविस्तार आप अंतर्निहित तर्क स्पष्ट कर देता है। (==) @Int 3 5तुलना 3और 5विशेष रूप से Intमूल्यों के रूप में । आप -स्पेशल तुलनात्मक फ़ंक्शन के @Intबजाय टाइप-विशिष्ट समानता फ़ंक्शन के शब्दकोश में एक कुंजी के रूप में सोच सकते हैं Int
चेपनर

जवाबों:


19

हाँ। इसे "डिक्शनरी पासिंग स्टाइल" कहा जाता है। कभी-कभी जब मैं कुछ विशेष रूप से मुश्किल काम कर रहा होता हूं, तो मुझे एक टाइपकास्ट को स्क्रैप करना होगा और इसे एक शब्दकोश में बदलना होगा, क्योंकि शब्दकोश पासिंग 1 अधिक शक्तिशाली है , फिर भी अक्सर काफी बोझिल हो जाता है, जिससे वैचारिक सरल कोड काफी जटिल दिखता है। मैं कभी-कभी ऐसी भाषाओं में शब्दकोश पासिंग शैली का उपयोग करता हूं जो टाइपकास्टेस का अनुकरण करने के लिए हस्केल नहीं हैं (लेकिन यह सीखा है कि यह आमतौर पर उतना अच्छा विचार नहीं है जितना लगता है)।

बेशक, जब भी अभिव्यंजक शक्ति में अंतर होता है, तो व्यापार बंद हो जाता है। यदि आप किसी दिए गए API का उपयोग अधिक तरीकों से कर सकते हैं यदि यह DPS का उपयोग करके लिखा गया है, तो API अधिक जानकारी प्राप्त कर सकता है यदि आप नहीं कर सकते हैं। व्यवहार में यह दिखाने का एक तरीका है Data.Set, जो इस तथ्य पर निर्भर करता है कि Ordप्रति प्रकार केवल एक शब्दकोश है। Setभंडार उसके तत्वों के अनुसार छाँटे गए Ord, और यदि आप एक शब्दकोश के साथ एक सेट का निर्माण, और फिर एक तत्व एक अलग से एक का उपयोग डाला, के रूप में डीपीएस के साथ संभव हो जाएगा, तो आप को तोड़ सकते थे Setके अपरिवर्तनीय और यह क्रैश हो। एक प्रेत अस्तित्व का उपयोग करके इस विशिष्टता समस्या को कम किया जा सकता हैएपीआई में काफी कष्टप्रद जटिलता की कीमत पर, शब्दकोश को चिह्नित करने के लिए, लेकिन फिर से टाइप करें। यह भी Typeableएपीआई में बहुत उसी तरह से पता चलता है।

विशिष्टता बिट बहुत बार नहीं आती है। आपके लिए कौन सी टाइपकास्ट बढ़िया हैं, यह आपके लिए कोड लिख रहा है। उदाहरण के लिए,

catProcs :: (i -> Maybe String) -> (i -> Maybe String) -> (i -> Maybe String)
catProcs f g = f <> g

जो दो "प्रोसेसर" लेता है जो एक इनपुट लेते हैं और आउटपुट दे सकते हैं, और उन्हें समतल कर सकते हैं, समतल करते हुए, Nothingडीपीएस में कुछ इस तरह लिखा जाना होगा:

catProcs f g = (<>) (funcSemi (maybeSemi listSemi)) f g

हमें अनिवार्य रूप से उस प्रकार को वर्तनी देना था जिसे हम इसे फिर से उपयोग कर रहे हैं, भले ही हमने पहले ही इसे टाइप सिग्नेचर में वर्तनी कर दिया था, और यहां तक ​​कि यह निरर्थक था क्योंकि कंपाइलर पहले से ही सभी प्रकार जानता है। क्योंकि Semigroupकिसी प्रकार पर दिए गए निर्माण का केवल एक ही तरीका है , संकलक आपके लिए यह कर सकता है। इसका "यौगिक हित" प्रकार का प्रभाव होता है जब आप बहुत सारे पैरामीट्रिक उदाहरणों को परिभाषित करना शुरू कर देते हैं और आपके प्रकारों की संरचना का उपयोग आप के लिए, जैसा कि Data.Functor.*कॉम्बिनेटरों में करते हैं , और इसका उपयोग बहुत प्रभाव के साथ किया जाता है deriving viaजहाँ आप अनिवार्य रूप से सभी प्राप्त कर सकते हैं। आपके लिए लिखी गई आपके प्रकार की "मानक" बीजीय संरचना।

और मुझे MPTC और फ़ंडेप्स पर भी आरंभ न करें, जो सूचना को वापस टाइपकास्ट और अनुमान में फीड करते हैं। मैंने कभी भी डीपीएस में ऐसी किसी चीज को परिवर्तित करने की कोशिश नहीं की है - मुझे संदेह है कि इसमें बहुत सारे प्रकार के समानता प्रमाण शामिल होंगे - लेकिन किसी भी मामले में मुझे यकीन है कि यह मेरे दिमाग के लिए बहुत अधिक काम होगा क्योंकि मैं आराम से रहूंगा। साथ में।

-

1 यू आप reflectionजिस स्थिति में उपयोग करते हैं , वे शक्ति के बराबर हो जाते हैं - लेकिन reflectionउपयोग करने के लिए बोझिल भी हो सकते हैं।



मुझे डीपीएस के माध्यम से व्यक्त किए गए फंड में बहुत रुचि है। क्या आप इस विषय पर कुछ सुझाए गए संसाधनों को जानते हैं? वैसे भी, बहुत समझदार व्याख्या।
बॉब

@ ओब, ऑफहैंड नहीं, लेकिन यह एक दिलचस्प अन्वेषण होगा। शायद इसके बारे में एक नया सवाल पूछें?
ल्यूकी

5

हाँ। वह (जिसे डिक्शनरी कहा जाता है) मूल रूप से कंपाइलर वैसे भी टाइपकास्ट करता है। उस फ़ंक्शन के लिए, शाब्दिक रूप से किया जाता है, यह इस तरह से दिखेगा:

elemBy :: (a -> a -> Bool) -> a -> [a] -> Bool
elemBy _ _ [] = False
elemBy eq x (y:ys) = eq x y || elemBy eq x ys

कॉलिंग elemBy (==) x xsअब इसके बराबर है elem x xs। और इस विशिष्ट मामले में, आप एक कदम आगे जा सकते हैं: eqहर बार एक ही पहला तर्क है, इसलिए आप इसे लागू करने के लिए कॉलर की जिम्मेदारी बना सकते हैं, और इसके साथ समाप्त हो सकते हैं:

elemBy2 :: (a -> Bool) -> [a] -> Bool
elemBy2 _ [] = False
elemBy2 eqx (y:ys) = eqx y || elemBy2 eqx ys

कॉलिंग elemBy2 (x ==) xsअब इसके बराबर है elem x xs

...अरे रुको। वह बस है any। (वास्तव में, मानक पुस्तकालय मेंelem = any . (==) )


AFAIU डिक्शनरी पासिंग स्कैला का दृष्टिकोण एन्कोडिंग प्रकार की कक्षाओं के लिए है। उन अतिरिक्त तर्कों को घोषित किया जा सकता है implicitऔर संकलक आपके लिए उन्हें दायरे से बाहर कर देगा।
michid
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.