2012-04-06 15 views
7

क्या जीएचसी को किसी विशेष मूल्य के जीवनकाल के लिए विशेष गणना करने के लिए मजबूर करने का कोई तरीका है?क्या हास्केल में कोई अंतर्निहित-आश याद है?

मैं स्पष्ट रूप से मूल्य को रिकॉर्ड में रख सकता हूं, जो गणना गणना के परिणाम के लिए आलसी रिकॉर्ड प्रविष्टियां बना सकता है, और एक निर्माता फ़ंक्शन बनाता है जो रिकॉर्ड बनाता है और कहा गया प्रविष्टियों में मूल्य को थंक करता है।

मुझे हर बार रिकॉर्ड से मूल मूल्य को खींचने की आवश्यकता से नफरत होगी। और हास्केल का कोई स्पष्ट रूप से पॉलीमोर्फिक नहीं है-सी ++ या जावा जैसे रिश्तों।

समान पैरामीटर वाले फ़ंक्शन के एकाधिक असंबद्ध आमंत्रणों में मानों को याद करने के लिए कोई चाल है?

मैं भरोसेमंद प्रकार के रूपों के साथ विभिन्न चालों की कल्पना कर सकता हूं जो प्रभावी रूप से संकलक को एकाधिक उपयोग आ रहे थे। हास्केल में कोई निर्भर प्रकार नहीं है लेकिन शायद अंतर्निहित पैरामीटर के आसपास कुछ है? मुझे नहीं लगता, लेकिन मैंने सोचा कि मैं पूछूंगा। शायद एक प्रज्ञा?


कल्पना कीजिए मैं Necklace डेटा संरचनाओं है जिसके लिए मैं परिमेय संख्याओं के एक परिणामस्वरूप वेक्टर, एक आम भाजक और अंश का एक वेक्टर के रूप में जमा की जरूरत का एक वेक्टर है।

{-# LANGUAGE ImplicitParams #-} 
import qualified Data.Vector as V 

data Necklace = Necklace { ... } 
necklace_length n = ... 

denominator :: (necklaces :: V.Vector Necklace) => Int 
denominator = V.foldl' lcm 30 $ V.map necklace_length ?necklaces 

numerators :: (necklaces :: V.Vector Necklace) => V.Vector Int 
numerators = V.map f ?necklaces 
    where f x = ... denominator ... 

kittytoy :: (necklaces :: V.Vector Necklace) => Meow -> ... 
kittytoy = \meow -> ... numerators ... 

एक प्रायोरी, मुझे लगता है कि उम्मीद थी, अगर मैं कई लाख kittytoy बार, हर आह्वान एक अलग पैरामीटर meow साथ, तो GHC कोड कि numerators एक लाख गुना, प्रत्येक का आह्वान एक समान निहित मापदंडों necklaces साथ पैदा करता है।

यह फिर भी स्पष्ट है कि numerators केवल एक बार लागू होने की आवश्यकता है, पहली बार ?necklaces असाइन किया जाता है, जिसका अर्थ है कि जीएचसी संभावित रूप से इस अनुकूलन को देख सकता है।

टेम्पलेट हैकेल का उपयोग करके स्पष्ट कोड रिफैक्टरिंग दृष्टिकोण भी होना चाहिए ताकि ?numerators = numerators जैसे कोड का उत्पादन करके थंक्स को स्पष्ट रूप से पास किया जा सके और इसे कॉल करने वाले कार्यों की बाधाओं को टाइप करने के लिए numerators :: V.Vector Int जोड़ना चाहिए।

+0

'kittytoy necklaces = n = numerators \ meow में हार -> सामग्री' निश्चित रूप से' n' को याद रखना चाहिए। यकीन नहीं है कि यह भी इस तरह से होगा। – yairchu

+0

क्या आपका मतलब है 'चलो k = kittytoy ...' 'k' के साथ प्रत्येक कॉल को' kittytoy' में बदल रहा है? हां, मैं सहमत हूं कि अंतर्निहित पैरामीटर 'हार' को याद रखना चाहिए, लेकिन क्या मुझे वास्तव में ऐसा करने की ज़रूरत है? –

+0

आह, नहीं, मैं 'kittertoy 'पर कॉल के बाहर' संख्याकार * * को याद करने की कोशिश कर रहा हूं, क्योंकि' किट्टीटोई 'को कई मिलियन बार बुलाया जाता है। हां, यह एक वैध बिंदु है कि 'kittytoy' को लैम्ब्डा अभिव्यक्ति होना चाहिए, भले ही मैं इसे स्पष्टता के लिए संपादित करूं। –

उत्तर

7

आप शायद data-memocombinators द्वारा कार्यान्वित किए गए शुद्ध ज्ञापन की तलाश में हैं। असल में, यह प्रत्येक पत्ते पर फ़ंक्शन के सभी संभावित मूल्यों के साथ एक (आलसी, संभवतः अनंत) वृक्ष संरचना बनाकर काम करता है, और उसके बाद एक नया फ़ंक्शन तैयार करता है जो प्रासंगिक स्थान पर मूल्य को आसानी से एक्सेस करता है। उदाहरण के लिए, आप कार्यों Bool -> a इस तरह के लिए एक memoiser लिख सकते हैं:

memoBool :: (Bool -> a) -> (Bool -> a) 
memoBool f = 
    let fTrue = f True 
     fFalse = f False 
    in \b -> if b then fTrue else fFalse 

इस मामले में, "वृक्ष संरचना" बल्कि बोन्साई है, केवल दो पत्ते रही है।

Memo a प्रकार, pair :: Memo a -> Memo b -> Memo (a, b) की तरह, forall r. (a -> r) -> (a -> r) के रूप में परिभाषित उपयोगी combinators साथ में डेटा-memocombinators संकुल इस अप (पढ़ें: यदि आप तर्क प्रकार a का काम करता है, और तर्क प्रकार b की memoise कार्यों memoise सकते हैं, आप के कार्यों memoise कर सकते हैं तर्क प्रकार (a, b))।

यह शुद्ध, और सुंदर सुरुचिपूर्ण है, मूल रूप से सभी हास्केल कार्यान्वयन द्वारा लागू साझाकरण पर निर्भर करता है (जो वही बात है जो आपके रिकॉर्ड विचार को काम करती है)।दुर्भाग्यवश, यह भी बहुत तेज़ नहीं है, इसलिए व्यावहारिक उपयोग के लिए आप uglymemo का उपयोग करना चाहेंगे, जो दृश्यों के पीछे एक परिवर्तनीय Map का उपयोग करता है (लेकिन बाहरी-शुद्ध इंटरफ़ेस का खुलासा करता है)।

+0

मुझे नहीं लगता, हालांकि यह जानना अच्छा है कि मौजूद है। मैं चाहता हूं कि जब ज्ञात पैरामीटर '? हार' परिवर्तन बदल जाए तो ज्ञापन डंप हो जाएंगे। मैंने yairchu टिप्पणी को स्पष्ट करने के लिए पाया, मूल रूप से निहित पैरामीटर अतिरिक्त अवसर पैदा कर सकते हैं, लेकिन केवल स्पष्ट रूप से लैम्ब्डा अभिव्यक्तियों को बनाकर। ऐसा लगता है कि अधिक संभव होना चाहिए, लेकिन ठीक है। –

+0

ठीक है, आप बस 'न्यूमेरेटर्स :: वी। वेक्टर हार -> वी। वेक्टर इंट' लिखेंगे। फिर, एक ही पैरामीटर के साथ कॉल पुनर्मूल्यांकन के बिना एक ही परिणाम उत्पन्न करेगा। माना जाता है कि, आपका 'वेक्टर' कितना बड़ा है, इस पर निर्भर करता है कि पेड़ की संरचना में इसे देखने की लागत खरोंच से 'संख्याकार' गणना करने की लागत से अधिक हो सकती है। जीएचसी में इनपुट मूल्यों की सूचक पहचान के आधार पर एक ज्ञापन पुस्तकालय बनाने की आवश्यक सुविधाएं हैं, लेकिन मुझे नहीं पता कि इसके लिए हैकेज पर कुछ भी है या नहीं। – ehird

+0

वैसे, निहित पैरामीटर बहुत दुर्लभ विस्तार हैं, और अधिकांश लोग उनसे बचते हैं - मैंने केवल कोड के दो टुकड़े देखे हैं जो वास्तव में उनका उपयोग करते हैं, और उनके पास बुरा नुकसान होता है, जैसे परिभाषा में एक प्रकार का हस्ताक्षर जोड़ना । – ehird

0

इस तथ्य से उत्पन्न एक और व्यावहारिक दृष्टिकोण है कि type अब Philip JF के answer here में उल्लेख किए गए प्रकार की बाधाओं के लिए समानार्थी परिभाषित किया गया है।

आप शायद एक प्रकार बाधा है कि सभी विभिन्न व्युत्पन्न मूल्यों के लिए निहित मापदंडों बनाई गई के लिए एक पर्याय बना सकते हैं:

type Necklaces = (necklaces :: V.Vector Necklace, 
        denominator :: Int, 
        numerators :: V.Vector Int) 

kittytoy :: (Necklaces) => Meow -> ... 

आप शुरू में किसी न किसी रूप से एक टेम्पलेट Haskell निर्माण का उपयोग कर ?numerators की तरह सभी मान निर्दिष्ट होता । यह देखने के लिए कि क्या यह काम करता है मैं इसके साथ खेलूँगा।