में ग्लोबल पॉलिमॉर्फिक (वर्ग) मानों का पुन: उपयोग/ज्ञापन, यदि मैं पॉलिमॉर्फिक "ग्लोबल" वर्ग मान साझा करता/याद करता हूं, विशेष रूप से मॉड्यूल सीमाओं में साझा किया जाता है। मैंने this और this पढ़ा है, लेकिन वे मेरी स्थिति को प्रतिबिंबित नहीं करते हैं, और मैं जवाब से क्या उम्मीद कर सकता हूं उससे कुछ अलग व्यवहार देख रहा हूं।हास्केल
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
module A
import Debug.Trace
class Costly a where
costly :: a
instance Num i => Costly i where
-- an expensive (but non-recursive) computation
costly = trace "costly!" $ (repeat 1) !! 10000000
foo :: Int
foo = costly + 1
costlyInt :: Int
costlyInt = costly
और एक अलग मॉड्यूल:
module B
import A
bar :: Int
bar = costly + 2
main = do
print foo
print bar
print costlyInt
print costlyInt
main
costly
की दो अलग-अलग मूल्यांकन पैदावार (के रूप में द्वारा संकेत चल रहा है
एक वर्ग है कि एक मूल्य है कि गणना करने के लिए महंगा हो सकता है को उजागर करता है पर विचार करें ट्रेस): foo
के लिए एक, और bar
के लिए एक। मुझे पता है कि costlyInt
सिर्फ रिटर्न foo
से (का मूल्यांकन) costly
, क्योंकि अगर मैं main
से print foo
को दूर तो पहले costlyInt
महंगा हो जाता है। (। मैं भी, कोई बात नहीं क्या एक अलग मूल्यांकन प्रदर्शन करने के लिए Num a => a
को foo
के प्रकार के सामान्यीकरण से costlyInt
पैदा कर सकता है)
मुझे लगता है कि मैं जानता हूँ कि क्यों इस व्यवहार होता है: Costly
के कहने प्रभावी रूप से एक समारोह है कि एक Num
लेता है शब्दकोश और Costly
शब्दकोश उत्पन्न करता है। तो bar
संकलित करते समय और costly
के संदर्भ को हल करते समय, ghc एक ताजा Costly
शब्दकोश उत्पन्न करता है, जिसमें इसका एक महंगा हिस्सा होता है। प्रश्न 1: क्या मैं इसके बारे में सही हूं?
costly
का सिर्फ एक मूल्यांकन पैदा करने के लिए कुछ तरीके, जिनमें निम्न शामिल हैं:
-
एक मॉड्यूल में
- रखो सब कुछ।
Num i
इंस्टेंस बाधा को हटाएं और केवलCostly Int
उदाहरण को परिभाषित करें।
दुर्भाग्य से, इन समाधानों में से एनालॉग मेरे कार्यक्रम में व्यावहारिक नहीं हैं - मैं अपने बहुरूपी रूप में वर्ग मान का उपयोग करती कई मॉड्यूल है, और केवल उच्च-स्तरीय स्रोत फ़ाइल में ठोस प्रकार के अंत में किया जाता है।
- उदाहरण में
costly
परिभाषा पर इनलाइन, INLINABLE, या NOINLINE का उपयोग करना:भी बदल जाता है कि जैसे मूल्यांकन, की संख्या को कम नहीं करते हैं। (मुझे यह काम करने की उम्मीद नहीं थी, लेकिन हे, एक शॉट के लायक।)
- उदाहरण परिभाषा में
SPECIALIZE instance Costly Int
प्रज्ञा का उपयोग करना।
बाद मेरे लिए आश्चर्य की बात है - मैं यह उम्मीद थी कि इसके बाद के संस्करण काम किया है दूसरे मद के लिए अनिवार्य रूप से बराबर हो। यही है, मैंने सोचा कि यह एक विशेष Costly Int
शब्दकोश उत्पन्न करेगा, जो foo
, bar
, और costlyInt
साझा करेगा। मेरा प्रश्न 2: मैं यहाँ क्या याद कर रहा हूँ?
मेरा अंतिम प्रश्न: क्या मैं चाहता हूं कि प्राप्त करने के लिए कोई अपेक्षाकृत सरल और मूर्ख तरीका है, यानी, किसी विशेष कंक्रीट प्रकार के costly
के सभी संदर्भ मॉड्यूल में साझा किए जा रहे हैं? जो मैंने अभी तक देखा है, उससे मुझे संदेह है कि जवाब नहीं है, लेकिन मैं अभी भी उम्मीद कर रहा हूं।
इस सवाल से अलग [मेरे पहले एक] (http://stackoverflow.com/questions/25057803/is-there-an-automatic-way-to-memoise-global-polymorphic-values-in- वास्तव में किस प्रकार है हास्केल)? – leftaroundabout
मैं जो कह सकता हूं उससे, आपके प्रश्न में लागत शब्दकोष के साथ संयुक्त रिकर्सन से आता है, जो घातीय पुनर्मूल्यांकन का कारण बनता है। एक बार उत्तरार्द्ध तय हो जाने के बाद, गणना स्वयं तेज है। लेकिन यदि दो मॉड्यूल fibsImplicitDict को संदर्भित करते हैं, तो उन्हें अलग-अलग थंक्स मिलेंगे जिन्हें अलग से मूल्यांकन किया जाएगा। मैं इसे बर्दाश्त नहीं कर सकता, क्योंकि मेरी गणना मूल रूप से महंगा है (रिकर्सन के कारण नहीं)। –
पीएस - तथ्य यह है कि उन पर बाधाओं के साथ कक्षा के उदाहरण भी एक भूमिका निभा रहे हैं, ऐसा लगता है। –