2012-02-15 18 views
5

प्रश्न। क्या इस कोड को स्पष्ट प्रकार के हस्ताक्षर के बिना काम करने का कोई तरीका है?जीएचसी प्रकार अनुमान वज़न

कोड। सबसे पहले, मेरे पास Data.Newtype से प्रेरित, एक अभ्यास-बहुत-अच्छा वैकल्पिक MonadTrans वर्ग है। यह तो इस तरह दिखता है,

{-# LANGUAGE FlexibleContexts, TypeFamilies #-} 

module Alt.Control.Monad.Trans where 

import Control.Monad 

class (Monad , Monad (BaseMonad)) => MonadTrans (:: * -> *) where 
    type BaseMonad :: * -> * 
    lift :: (BaseMonad) α -> α 

, मैं विधि foo के साथ एक कक्षा A है, और यदि कुछ आधार इकाई M एक A है, तो किसी भी तब्दील इकाई T M भी एक A है। कोड में,

class A where 
    foo :: String -> () 

instance (A (BaseMonad), MonadTrans) => A where 
    foo n = lift $ foo n 

हालांकि, अगर मैं अब अपनी पहली तर्क प्रतिस्थापित साथ foo के लिए एक शॉर्टकट बनाना चाहते हैं, तो मैं एक स्पष्ट प्रकार हस्ताक्षर, या संकलक के संदर्भ ढेर अतिप्रवाह की जरूरत है।

minimize_call :: A => () 
minimize_call = foo "minimize" 

संभव जानकारी अनुमान में मदद करेगा। मान लें कि हमारे पास एक संबद्ध प्रकार B :: * -> * है। मैं सोच रहा हूं कि मैं संकलक B को B t /= t, B (B t) /= B t इत्यादि को संतुष्ट करता हूं यानी B किसी भी तरह "monotonic" है - जो संबंधित प्रकार का पीछा करते हैं, नए प्रकार के रैपर को हटाने के बराबर है, और यह जानना चाहिए कि यह हमेशा के लिए नए प्रकार के रैपर को नहीं हटा सकता , इसलिए हस्ताक्षर के लिए संदर्भ A जोड़ना जरूरी है।

+0

क्षमा करें, मुझे याद रखने के लिए परेशान होना चाहिए _why_ मैंने वैकल्पिक 'मोनाडट्रान' पर स्विच किया है ... अभी मान लें कि यह क्लीनर कोड उत्पन्न करता है, लेकिन मुझे लगता है कि एक और अधिक महत्वपूर्ण कारण था। – gatoatigrado

+0

दिलचस्प सवाल। हालांकि आप एक स्पष्ट प्रकार के हस्ताक्षर क्यों नहीं चाहते हैं? 'Minimize_call' को कुछ निश्चित मान नहीं होना चाहिए, न कि पॉलिमॉर्फिक निरंतर (या शायद आप इसे पॉलिमॉर्फिक प्राप्त कर सकते हैं, मुझे यकीन नहीं है)? यदि इसमें कुछ निश्चित प्रकार है, तो मैं इसे दस्तावेज करता हूं, और यदि ऐसा नहीं होता है, तो मैं ** ** ** दस्तावेज़ दूंगा। पाठक को अपने सिर में पूरे प्रोग्राम विश्लेषण करने के लिए मजबूर करना यह पता लगाने के लिए कि 'minimize_call' किस प्रकार का काउंटर-उत्पादक लगता है। – Ben

+0

@ बेन, यह सच है कि, इस मामले में, 'minimize_call' के लिए एक प्रकार का हस्ताक्षर होना अच्छा अभ्यास है।हालांकि, टाइप अनुमान को तोड़ने से पता चलता है कि कुछ गलत हो रहा है (डिजाइनर, कंपाइलर या कंपाइलर के साथ संचार के साथ), और संभावित रूप से समस्याएं पैदा कर सकती हैं, अनावश्यक त्रुटि संदेशों का उल्लेख नहीं करना। – gatoatigrado

उत्तर

3

हाँ, एक तरीका है। A के लिए एक ग्राउंड उदाहरण प्रदान करें, और भाषा प्रागमा में NoMonomorphismRestriction जोड़ें (FlexibleInstances और UndecidableInstances के अतिरिक्त भी)।

हालांकि, A कक्षा अनुपयोगी होगी। कंपाइलर को यह जानने का कोई तरीका नहीं है कि MonadTrans उदाहरण BaseMonad m = m के साथ कभी भी नहीं होगा। इस प्रकार यह कभी भी एक उदाहरण का चयन नहीं कर सकता है, क्योंकि यह नहीं पता कि यहां या किसी अन्य से उदाहरण का उपयोग करना है या नहीं।

{-# LANGUAGE FlexibleContexts, TypeFamilies, FlexibleInstances, UndecidableInstances, NoMonomorphismRestriction #-} 

module Trans (MonadTrans(..), A(..), minimize_call) where 

import Control.Monad 

class (Monad m, Monad (BaseMonad m)) => MonadTrans (m :: * -> *) where 
    type BaseMonad m :: * -> * 
    lift :: (BaseMonad m) α -> m α 

class A m where 
    foo :: String -> m() 


data Foo a = Bork 

instance Monad Foo where 
    return _ = Bork 
    _ >>= _ = Bork 

instance A Foo where 
    foo _ = Bork 


instance (A (BaseMonad m), MonadTrans m) => A m where 
    foo n = lift $ foo n 

-- minimize_call :: A m => m() 
minimize_call = foo "minimize" 

ghc 6.12, 7.0, 7.2 और 7.4 के साथ संकलित करता है। हस्ताक्षर के बिना, minimize_call एक मोनोमोर्फिक प्रकार प्राप्त करना चाहिए, जब तक एमआर बंद नहीं हो जाता है। यह वैसे भी काम नहीं कर सकता क्योंकि बाधा A m डिफ़ॉल्ट नहीं है। तो इसलिए एमआर बंद कर दिया जाना चाहिए। लेकिन फिर टाइपर चेकर अभी भी अपनी खुद की पूंछ का पीछा करता है ताकि बाधा साबित हो सके संतोषजनक हो। केवल उठाने के उदाहरण के साथ, यह नहीं कर सकता है। यदि आप एक एंकर प्रदान करते हैं, तो यह कर सकता है।

लेकिन एक प्रकार का हस्ताक्षर प्रदान करना बहुत बेहतर है।

+0

धन्यवाद, लेकिन मैं मॉड्यूल में ग्राउंडेड उदाहरण नहीं चाहता हूं। वास्तव में, मेरे संकलक के पास कितने बैकएंड हैं, और यह मानते हुए कि एक विशेष का उपयोग अवांछित है, इस पर निर्भर करता है कि कई आधारभूत उदाहरण हो सकते हैं। मेरे पास पहले से ही 'फ्लेक्सिबल इंस्टेंस', 'फ्लेक्सिबल कॉन्टैक्स' है, और 'नोमोनोमोर्फिज्म रेस्ट्रिक्शन' चालू है। – gatoatigrado

+1

आप एक निर्यात-निर्यात डमी मोनड का उपयोग कर सकते हैं, अपडेट देखें। 'Minimize_call' का अनुमानित प्रकार' ए एम => एम() 'है, जैसा कि होना चाहिए, यह कहीं और अलग ग्राउंड किए गए उदाहरणों का उपयोग नहीं करता है, टाइपर को समाप्त करने के लिए बस जरूरी है। –

+0

दरअसल, नहीं, आप 'minimize_call', या' foo' का उपयोग नहीं कर सकते हैं। हस्ताक्षर के साथ या बिना। –

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