2012-09-18 29 views
6

का व्युत्पन्न चर रोकना मैं लाइब्रेरी के लिए एक प्रकार का वर्ग लिख रहा हूं ताकि एक अमूर्त इंटरफ़ेस को Proxy-जैसी प्रकारों को परिभाषित किया जा सके। प्रकार वर्ग लग रहा है कि:किसी प्रकार की कक्षा या एक उदाहरण

class ProxyC p where 
    idT :: (Monad m) => b' -> p a' a b' b m r 
    (<-<) :: (Monad m) 
      => (c' -> p b' b c' c m r) 
      -> (b' -> p a' a b' b m r) 
      -> (c' -> p a' a c' c m r) 
    ... -- other methods 

मैं भी Proxy प्रकार है कि के रूप में हैं के लिए एक्सटेंशन लिख रहा हूँ:

instance (ProxyC p) => ProxyC (SomeExtension p) where .... 

... और मुझे इन उदाहरणों चाहते हैं सक्षम होने के लिए एक अतिरिक्त बाधा लगाने के लिए कि mMonad है तो p a' a b' b ma', a, b', और b के लिए Monad है।

हालांकि, मुझे कोई संकेत नहीं है कि ProxyC कक्षा या उदाहरणों के लिए या तो बाधा के रूप में इसे एन्कोड करना है। एकमात्र समाधान मैं वर्तमान में पता है के वर्ग के विधि हस्ताक्षर में यह एन्कोडिंग की तरह कुछ करने के लिए है:

(<-<) :: (Monad m, Monad (p b' b c' c m), Monad (p a' a b' b m)) 
      => (c' -> p b' b c' c m r) 
      -> (b' -> p a' a b' b m r) 
      -> (c' -> p a' a c' c m r) 

... लेकिन मैं उम्मीद कर रही थी कि वहाँ एक सरल और अधिक सुरुचिपूर्ण समाधान होगा।

संपादित: और भी नहीं है कि पिछले समाधान, काम करता है के बाद से संकलक अनुमान नहीं है कि (Monad (SomeExtension p a' a b' b m)) चर का एक विशिष्ट विकल्प, तब भी जब निम्नलिखित उदाहरण दिए गए के लिए निकलता है (Monad (p a' a b' b m)): #

instance (Monad (p a b m)) => Monad (SomeExtension p a b m) where ... 

संपादित करें 2: अगले समाधान मैं विचार कर रहा हूँ बस ProxyC वर्ग के भीतर Monad वर्ग के लिए तरीकों डुप्लिकेट कर रही है:

class ProxyC p where 
    return' :: (Monad m) => r -> p a' a b' b m r 
    (!>=) :: (Monad m) => ... 

... और फिर प्रत्येक ProxyC उदाहरण के साथ उन्हें तुरंत चालू करना। यह मेरे उद्देश्यों के लिए ठीक लगता है क्योंकि Monad विधियों को केवल विस्तार लेखन के लिए आंतरिक रूप से उपयोग करने की आवश्यकता है और मूल प्रकार के पास डाउनस्ट्रीम उपयोगकर्ता के लिए उचित Monad उदाहरण है। यह सब सिर्फ उदाहरण लेखक को Monad विधियों का खुलासा करता है।

+0

AFAIK आप केवल बदसूरत हैक के साथ ऐसा कर सकते हैं, जैसे f.e. एडवर्ड Kmett http://hackage.haskell.org/packages/archive/constraints/0.3.2/doc/html/Data-Constraint-Forall.html –

उत्तर

1

यह करने के लिए एक नहीं बल्कि तुच्छ तरीका मूल्य स्तर

data IsMonad m where 
    IsMonad :: Monad m => IsMonad m 

class ProxyC p where 
    getProxyMonad :: Monad m => IsMonad (p a' a b' b m) 

आप स्पष्ट रूप से शब्दकोश खोलने के लिए भी आप की जरूरत है यह

--help avoid type signatures 
monadOf :: IsMonad m -> m a -> IsMonad m 
monadOf = const 

--later on 
case getProxyMonad `monadOf` ... of 
    IsMonad -> ... 

की आवश्यकता होगी करने के लिए सबूत ले जाने के लिए एक GADT का उपयोग करें प्रस्तावों के सबूत पास करने के लिए जीएडीटी का उपयोग करने की रणनीति वास्तव में बहुत सामान्य है।आप बाधा प्रकार, और न सिर्फ GADTs का उपयोग कर ठीक कर रहे हैं, आप के बजाय एडवर्ड Kmett के Data.Constraint पैकेज का उपयोग कर सकते

class ProxyC p where 
    getProxyMonad :: Monad m => Dict (Monad (p a' a b' b m)) 
जो आप

getProxyMonad' :: ProxyC p => (Monad m) :- (Monad (p a' a b' b m)) 
getProxyMonad' = Sub getProxyMonad 

परिभाषित और फिर एक कल्पना इन्फ़िक्स ऑपरेटर का उपयोग संकलक बताने के लिए देता है

जहां इकाई उदाहरण

... \\ getProxyMonad' 
वास्तव में

देखने के लिए, :- अनुलाग प्रकार एक वर्ग (जहां वस्तुओं चोर हैं रूपों बाधाएं), और इस श्रेणी में अच्छी संरचना के बहुत हैं, जो कहने के लिए सबूत करना बहुत अच्छा है।

पेज। इनमें से कोई भी स्निपेट परीक्षण नहीं किया जाता है।

संपादित करें: आप भी मूल्य स्तर सबूत एक newtype आवरण के साथ और जोड़ सकता नहीं सब जगह

newtype WrapP p a' a b' b m r = WrapP {unWrapP :: p a' a b' b m r} 

instance ProxyC p => Monad (WrapP p) where 
    return = case getProxyMonad of 
       Dict -> WrapP . return 
    (>>=) = case getProxyMonad of 
       Dict -> \m f -> WrapP $ (unWrapP m) >>= (unWrapP . f) 

instance ProxyC p => ProxyC (WrapP p) where 
    ... 

मुझे लगता है खत्म हो गया GADTs खोलने की जरूरत है, लेकिन स्पष्ट रूप से परीक्षण नहीं किया है कि इस कार्यान्वयन भी होगा अपेक्षाकृत कुशल हो।

+0

में मुझे लगता है कि इस बारे में मेरी एकमात्र चिंता यह है कि इसके लिए कितना ओवरहेड है रैपिंग और 'डेटा' प्रकार को खोलना। याद रखें कि मैं हर बांध पर ऐसी गोल यात्रा करूँगा। हालांकि, मैंने इसे बेंचमार्क नहीं किया है, इसलिए यह मेरे हिस्से पर शुद्ध अटकलें है। अभी मेरे पास एक और समाधान है जो कुछ ऐसा दिखता है: 'newtype p pa' ab 'bmr = p (pa' ab 'bmr)' और फिर मैं 'इंस्टेंस (प्रॉक्सीसी पी, मोनाड एम) => मोनाड (पी पी' अब लिखता हूं 'बीएम) जहां ...', और मैं अपने हस्ताक्षर में 'पी' रखने के लिए सभी' प्रॉक्सीसी 'विधियों को बदलता हूं। –

+0

शब्दकोश संशोधन की चाल ने काम किया, हालांकि मैं इसे करने के लिए एडवर्ड के 'बाधा' पैकेज का उपयोग कर समाप्त हुआ। –

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