2013-11-02 11 views
11

के लिए एक फ़ंक्शन को विशेषज्ञता देने वाले नियम को फिर से लिखना जीएचसी RULES pragma का उपयोग करके, विशिष्ट प्रकारों के लिए एक पॉलिमॉर्फिक फ़ंक्शन का विशेषज्ञ होना संभव है। हास्केल रिपोर्ट से उदाहरण:जीएचसी एक प्रकार के वर्ग

genericLookup :: Ord a => Table a b -> a -> b 
intLookup  ::   Table Int b -> Int -> b 

{-# RULES "genericLookup/Int" genericLookup = intLookup #-} 

यह GHC एक पूर्णांक अनुक्रमित मेज और जेनेरिक वर्जन अन्यथा, जहां intLookup शायद और अधिक कुशल हो जाएगा पर intLookup का उपयोग होगा।

मैं कुछ इसी तरह पूरा करने के लिए, निम्न (थोड़ा सरलीकृत) लोगों की तरह काम करता है का उपयोग कर चाहते हैं:

lookup :: Eq a => [(a, b)] -> a -> b 
lookupOrd :: Ord a => [(a, b)] -> a -> b 

जहां lookupOrd इनपुट सूची में से एक Map बनाता है और फिर Map.lookup का उपयोग करता है, जो कि a एक हो की आवश्यकता है Ord के सदस्य।

अब मैं GHC बताने के लिए जब भी a वास्तव में Ord प्रकार वर्ग का एक सदस्य है कि lookupOrdlookup के बजाय इस्तेमाल किया जाना चाहिए चाहते हैं। निम्नलिखित नियम, तथापि, typecheck नहीं करता है:

{-# RULES "lookup/Ord" lookup = lookupOrd #-} 

GHC (हक) की शिकायत है कि यह संदर्भ (Eq a) से (Ord a) अनुमान नहीं कर सकते। क्या कोई पुनर्लेखन नियम है जो मुझे इस तरह के प्रकार के वर्ग-आधारित विशेषज्ञता को करने की अनुमति देगा?

+7

यह पुरानी [खुली दुनिया की समस्या] में बहुत अधिक चल रहा है (http://stackoverflow.com/a/1072523/745903): आप इस पर आधारित निर्णय लेने की कोशिश कर रहे हैं कि किसी प्रकार में कोई प्रकार है या नहीं वर्ग टाइप करें। _But हास्केल की कोई धारणा नहीं है ** ** ** एक प्रकार के वर्ग_ में नहीं है! यह हमेशा माना जाता है कि किसी भी प्रकार के किसी भी वर्ग में हो सकता है (भले ही ऐसा कोई उदाहरण सामने नहीं आया है, फिर भी कोई इसे बाद में जोड़ सकता है)। – leftaroundabout

+3

@ बाएंराउंडबाउट यह समस्या बहुत गंभीर नहीं है; इस तरह के नियम लागू करने के लिए एक सर्वोत्तम प्रयास दृष्टिकोण कल्पना की जा सकती है (यदि जीएचसी इसे पहले स्थान पर समर्थन देगी)। –

उत्तर

13

मुझे नहीं लगता कि वहाँ है, और वहाँ एक कारण है कि यह आसानी से GHC की वर्तमान कार्यान्वयन के साथ संभव है:

यद्यपि आप हास्केल वाक्य रचना में नियमों को निर्दिष्ट, वे जा रहे हैं GHC कोर भाषा को लागू किया जा करने के लिए । वहाँ, प्रकार वर्ग की कमी शब्दकोश तर्क में बदल गया है, इसलिए समारोह

lookup :: Eq a => a -> [(a,b)] -> Maybe b 

अब टाइप है

lookup :: forall a b. Eq a -> a -> [(a, b)] -> Maybe b 

प्रकार

lookupOrd :: forall a b. Ord a -> a -> [(a, b)] -> Maybe b 

जहां Eq a और Ord a है, जबकि अपने lookupOrd होता सामान्य डेटा प्रकार बनें। विशेष रूप से, इस चरण में, टाइप क्लास के किसी भी प्रकार के लिए कोई विचार नहीं है; सब कुछ पहले हल किया गया है।

तो अब मान संकलक

lookup (dict :: Eq MyType) (x :: MyType) (list :: [(MyType, String)]) 

का एक घटना क्या यह इसके साथ बदलना चाहिए पाता है? आपने उसे बताया कि x और list को lookupOrd पर भी पास किया जा सकता है, लेकिन यह फ़ंक्शन Ord MyType प्रकार का मान भी चाहता है, जो नियम के बाईं ओर नहीं होता है। तो जीएचसी को हारना है।

{-# RULES "lookup/Ord" forall a x. lookup a x = lookupOrd (a::()) x #-} 

काम करता है, हालांकि, के रूप में यहाँ समस्याग्रस्त तर्क (Ord शब्दकोश) पहले से ही शासन में तय हो गई है, और की जरूरत नहीं है की तरह एक नियम जब शासन लागू करने के पाया जा सकता है।

प्रिंसिपल में, अन्य कंपाइलर डिज़ाइन आपके इच्छित फॉर्म के नियमों की अनुमति दे सकते हैं।

+0

जीएचसी 8.0.1 शिकायत नहीं करता है अगर आप '{- # नियम "लुकअप/ऑर्ड" फोरल (ई :: ऑर्ड के => के) लिखते हैं (एल :: [(के, ए)])। लुकअप ई एल = लुकअपऑर्ड ई एल # -} ', लेकिन नियम वास्तव में आग लग रहा है। –

+0

जीएडीटी के चेहरे में यह और विशेषज्ञता दोनों ट्रैक्टबल हो सकती है अगर जीएचसी टाइपिंग जांच के बाद अपनी इंस्टेंस रिज़ॉल्यूशन मशीनरी पर पकड़ लेती है। – dfeuer

1

हालांकि यह एक पुराना सवाल है, भविष्य में Google'ers को यह जानने में रुचि हो सकती है कि ifcxt पैकेज का उपयोग करके ओपी क्या करना चाहता था।

आप अधिक उदाहरणों के लिए प्रलेखन देख सकते हैं, लेकिन मूल रूप से आप दूसरे उदाहरण का उपयोग करेंगे, उदाहरण 2: आधार के रूप में अपना कोड asymptotically कुशल बनाएं।

दो कार्यों के साथ

,

lookup :: Eq a => [(a, b)] -> a -> b 
lookupOrd :: Ord a => [(a, b)] -> a -> b 

आप बनाना होगा,

cxtLookup :: forall a. (Eq a, IfCxt (Ord a)) => [(a, b)] -> a -> b 
cxtLookup = ifCxt (Proxy::Proxy (Ord a)) lookupOrd lookup 

जो तुम पर निर्भर करता है जो सबसे प्रभावी समारोह का चयन करने के लिए अनुमति देगा अपने डेटा संरचना लागू typeclasses।

नोट, मुझे नहीं पता कि यह प्रदर्शन को कितना प्रभावित करेगा, लेकिन मुझे लगता है कि यह लुकअप फ़ंक्शंस के रनटाइम की तुलना में तुच्छ है, और इसलिए वास्तव में इसके लायक है।

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