कुछ दृष्टिकोण हैं जो आप ले सकते हैं; मुझे नहीं लगता कि आपने यह निर्धारित करने के लिए पर्याप्त संदर्भ प्रदान किया है कि कौन सा सबसे उपयुक्त होगा। यदि आप जीएचसी-7.4 का उपयोग कर रहे हैं, तो आप DefaultSignatures
एक्सटेंशन को आजमा सकते हैं।
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DefaultSignatures #-}
-- A generic class with a generic function.
class Foo a where
foo :: a -> a
default foo :: Bar a => a -> a
foo = bar . baz
-- A specific class with specific functions.
class Bar a where
bar :: a -> a
baz :: a -> a
instance Bar String where
bar = id
baz = id
instance Foo String
main :: IO()
main =
putStrLn (foo "bar")
तुम अब भी घोषित करने के लिए है कि एक प्रकार Foo
का एक उदाहरण है की जरूरत है, लेकिन आप विधि घोषणा को दोहराने के लिए क्योंकि डिफ़ॉल्ट कार्यान्वयन का उपयोग किया जाएगा जरूरत नहीं है।
एक और काफी हल्का दृष्टिकोण एक नया प्रकार का उपयोग करना है। यदि आपके पास ऐसे फ़ंक्शन हैं जिन्हें Foo
उदाहरण की आवश्यकता है, तो आप नए टाइप में Bar
इंस्टेंस को लपेट सकते हैं।
newtype FooBar a = FooBar { unFooBar :: a }
instance Bar a => Foo (FooBar a) where
foo = FooBar . bar . baz . unFooBar
-- imported from a library or something...
needsFoo :: Foo a => a -> b
myFunc = needsFoo (FooBar someBar)
वैकल्पिक रूप से, आप Bar
उदाहरण के लिए एक सामान्य कार्य के साथ foo
की जगह, या एक विशेष संस्करण बनाने के साथ द्वारा प्राप्त करने में सक्षम हो सकता है:
-- if every `Foo` is also a `Bar`, you can just do this. No need for `Foo` at all!
foo :: Bar a => a -> a
foo = bar . baz
-- if most `Foo`s aren't `Bar`s, you may be able to use this function when you have a `Bar`
fooBar :: Bar a => a -> a
foo = bar . baz
ये शायद सबसे अच्छा समाधान कर रहे हैं अगर वे के लिए काम आपकी स्थिति।
एक और विकल्प मैन्युअल रूप से प्रत्येक Foo
उदाहरण घोषित करना है। यद्यपि कई अलग-अलग कल्पनाशील उदाहरण हो सकते हैं, लेकिन कोडबेस के लिए यह काफी आम है कि वास्तव में केवल कुछ उदाहरण हैं जिनका उपयोग वास्तव में किया जाता है। यदि यह यहां सच है, तो शायद अधिक सामान्य समाधान को लागू करने के बजाय आपको आवश्यक 3 या 4 उदाहरणों को लिखने के लिए शायद कम काम है।
एक बहुत ही अंतिम उपाय के रूप में, आप अपने मूल कोड की तरह कुछ का उपयोग कर सकते हैं, लेकिन आप भी OverlappingInstances
जरूरत है यह काम करने के लिए (यदि आप OverlappingInstances
की जरूरत नहीं है, तो आप एक Foo
वर्ग की जरूरत नहीं है)। यह वह एक्सटेंशन है जो कई उपलब्ध मैचों में जीएचसी को "सबसे विशिष्ट उदाहरण" चुनने की अनुमति देता है। यह कम या ज्यादा काम करेगा, हालांकि आपको वह उम्मीद नहीं मिल सकती है जो आप उम्मीद करते हैं।
class Foo a where
foo :: a -> a
class Bar a where
bar :: a -> a
baz :: a -> a
instance Bar String where
bar = id
baz = id
instance Bar a => Foo a where
foo = bar . baz
instance Foo [a] where
foo _ = []
main :: IO()
main =
print (foo "foo")
अब main
एक खाली स्ट्रिंग प्रिंट करता है। a
और [a]
के लिए दो Foo
उदाहरण हैं। उत्तरार्द्ध अधिक विशिष्ट है, इसलिए इसे foo "foo"
के लिए चुना जाता है क्योंकि स्ट्रिंग में [Char]
टाइप होता है, हालांकि आप शायद पूर्व चाहते थे। तो अब आप भी
instance Foo String where
foo = bar . baz
लिखने के लिए इसके बाद से आप के रूप में अच्छी पूरी तरह से बाहर छोड़ सकते हैं Bar a => Foo a
उदाहरण देख सकते हैं।
'उदाहरण बार एक => फू की घोषणा A' आप हर' A' के लिए एक उदाहरण पेश किया है से - संदर्भ 'बार A' उदाहरण चयन में नहीं किया जाता है - हालांकि अगर आप अतिव्यापी इंस्टेंस GHC सबसे मिलेगा प्रति मॉड्यूल आधार पर विशिष्ट एक। –
यह है ... काउंटर अंतर्ज्ञानी :-) क्या इसके चारों ओर कोई रास्ता है? मुझे लगता है कि "सबसे विशिष्ट उदाहरण ढूंढना" है जो 'UndecidableInstances' करने का प्रयास करेगा, लेकिन मेरे कोड में यह बुरी तरह विफल हो जाता है। –
संबंधित: http://stackoverflow.com/questions/3213490 – sdcvvc