2017-10-09 11 views
6

पर पाशन से रोकथाम परस्पर पुनरावर्ती डिफ़ॉल्ट तरीकों मैं वर्तमान में निम्नलिखित की तरह एक संरचना है:क्रम

class F a where 
    f :: ... 
    default f :: (G a...) => ... 
    f = (some definition in terms of g) 

class F a => G a where 
    g :: ... 
    default g :: (C a...) => ... 
    g = (some definition in terms of f) 

उम्मीद है कि कुछ हद तक सादे अंग्रेजी में, मैं g हमेशा के मामले में f लिख सकते हैं। मैं gf के संदर्भ में कभी-कभी लिख सकता हूं, अर्थात् aC बाधा को संतुष्ट करता है। अगर किसी को लिखते हैं, के लिए एक प्रकार T संतोषजनक C T

instance F T 
instance G T 

इस क्रम में संकलन और पाश होगा कहना

मुद्दा मैं यहाँ देखते हैं। जबकि दोनों डिफ़ॉल्ट परिभाषाएं सही हैं, कम से कम एक को परिभाषित करना महत्वपूर्ण है।

प्रगामा के साथ मैं इसे हल कर सकता हूं अगर f और g एक ही कक्षा में थे, लेकिन इस मामले में वे नहीं हैं।

इसके अलावा एक ही कक्षा में f और g दोनों रखने, संभव हो सकता है क्योंकि जहां वहाँ g के हर परिभाषा के लिए f की एक परिभाषा है प्रतीत नहीं होता है, वहाँ f के हर परिभाषा के लिए g की एक परिभाषा नहीं है। एक संभावना gF में बढ़ रही है, लेकिन C a उस पर बाधा डाल रही है, लेकिन यह मुझे को किसी भी a के लिए गैर-डिफ़ॉल्ट परिभाषा के साथ परिभाषित करने से रोकती है जो C a को संतुष्ट नहीं करती है।

क्या इस दुविधा को हल करने के लिए इसे पुनर्गठित करने का कोई तरीका है?

+1

एक और वापस आने विकल्प 'g' और/या' f' की डिफ़ॉल्ट परिभाषा के लिए नहीं है, लेकिन बजाय एक स्टैंडअलोन समारोह है कि उदाहरण के लेखकों के लिए स्पष्ट रूप से करने के लिए * * विकल्प के रूप में उपयोग कर सकते हैं प्रदान करने के लिए किया जाएगा "डिफ़ॉल्ट" कार्यान्वयन ('g = defaultG' लिखकर)। उम्मीद है कि कम से कम एक * गलती से * दोनों को डिफ़ॉल्ट रूप से छोड़ दें, क्योंकि कम से कम एक जानबूझकर विकल्प था। – Ben

उत्तर

0

मेरा पिछला उत्तर बकवास था, इसलिए इसके बजाय यहां एक (उम्मीद है) बेहतर है। यह कम से कम संकलन समय पर आपको चेतावनी देगा। चाल वर्ग G में f' या g लागू करने के लिए करता है, तो दोनों aF और G दोनों है, लेकिन केवल f अगर G के कहने असंभव है के लिए उदाहरण हैं है।

{-# LANGUAGE DefaultSignatures #-} 

class C a where 

class F a where 
    f :: a -> a 
    default f :: (G a) => a -> a 
    f = g 

class F a => G a where 
    {-# MINIMAL (f'|g) #-} 

    f' :: a -> a 
    f' = f 

    g :: a -> a 
    default g :: (C a) => a -> a 
    g = f' 

instance F Integer where 
    f = succ 

instance F Int 
instance G Int where 
    g = succ 

instance C Float 
instance F Float 
instance G Float where 
    f' = succ 

-- This will give a compile time warning, but will still 
-- loop at runtime: 
instance C Double 
instance F Double 
instance G Double