2017-06-24 10 views
6

यदि मैं Identity के लिए मोनैड ट्रांसफार्मर प्रकार को परिभाषित करता हूं, तो यह Show उदाहरण प्राप्त करने में सक्षम है।शायद उदाहरण के लिए शो उदाहरण क्यों नहीं लिया जा सकता है?

newtype IdentityT f a = 
    IdentityT { runIdentityT :: f a } 
    deriving (Show) 

instance Show (f a) => Show (IdentityT f a) 

प्राप्त होगा लेकिन अगर मैं के लिए Maybe

newtype MaybeT m a = 
    MaybeT { runMaybeT :: m (Maybe a) } 
    deriving (Show) 

इकाई ट्रांसफार्मर के प्रकार को परिभाषित मैं त्रुटि मिलती है

• No instance for (Show (m (Maybe a))) 
     arising from the first field of ‘MaybeT’ (type ‘m (Maybe a)’) 

के बाद से 0 एक Show उदाहरण है, मैं इसे काम करते हैं और प्राप्त करने के लिए उम्मीद करेंगे

instance Show (m (Maybe a)) => Show (MaybeT m a) 

क्यों नहीं कर सकते?

उत्तर

3

जीएचसी यह निर्धारित करने के लिए एक हेरिस्टिक का उपयोग करता है कि कोई उदाहरण खोज समाप्ति की गारंटी देता है या नहीं। यहां समाप्ति से, हमारा मतलब है कि, उदाहरण के लिए खोज करते समय हम हमेशा के लिए लूप नहीं करेंगे। वस्तुतः, इस के लिए मना किया जाना चाहिए

instance Show a => Show a where ... 

के साथ ही इस

instance Show [a] => Show a where ... 

GHC मोटे तौर पर की आवश्यकता है कि उदाहरण के संदर्भ (=> पहले वाला भाग) में कमी होना चाहिए "छोटे" में बाधा से सिर (=> के बाद)। इसलिए, यह इस स्वीकार करता है:

instance Show a => Show [a] where ... 

a के बाद से एक प्रकार निर्माता [a] की तुलना में कम होता है।

यह भी इस स्वीकार करता है:

instance Show (f a) => Show (IdentityT f a) where ... 

के बाद से f a एक प्रकार निर्माता IdentityT f a की तुलना में कम होता है।

हालांकि,

instance Show (f (Maybe a)) => Show (MaybeT f a) where ... 

निर्माताओं की एक ही नंबर का उपयोग करता है! इसलिए, यह सुनिश्चित करने के लिए स्वीकार नहीं किया जाता है कि यह एक लूप का कारण नहीं बनता है। सब के बाद, बाद में, हम

instance Show (MaybeT f a)) => Show (f (Maybe a)) where ... 

को पूरा हो सकता है और यह स्पष्ट है कि इन दो में से कम से कम एक समाप्ति की गारंटी करने को अस्वीकार कर दिया जाना चाहिए है।जीएचसी दोनों को अस्वीकार करने का विकल्प चुनता है।

UndecidableInstances इस प्रतिबंध को आराम देता है। जीएचसी दोनों उदाहरण स्वीकार करेगा, और अब लूप से बचने के लिए बोझ हमारे ऊपर है।

5

मुझे लगता है कि हम GHC के सुझाव मान (मैं 8.2.1 का उपयोग कर रहा) द्वारा इस मुद्दे को देख सकते हैं जब तक हम एक मरे हुए अंत हिट:

Prelude> :{ 
Prelude| newtype MaybeT m a = 
Prelude| MaybeT { runMaybeT :: m (Maybe a) } 
Prelude| deriving (Show) 
Prelude| :} 

<interactive>:12:13: error: 
    • No instance for (Show (m (Maybe a))) 
     arising from the first field of ‘MaybeT’ (type ‘m (Maybe a)’) 
     Possible fix: 
     use a standalone 'deriving instance' declaration, 
      so you can specify the instance context yourself 
    • When deriving the instance for (Show (MaybeT m a)) 
Prelude> :set -XStandaloneDeriving 
Prelude> deriving instance Show (m (Maybe a)) => Show (MaybeT m a) 

<interactive>:17:19: error: 
    • The constraint ‘Show (m (Maybe a))’ 
     is no smaller than the instance head 
     (Use UndecidableInstances to permit this) 
    • In the stand-alone deriving instance for 
     ‘Show (m (Maybe a)) => Show (MaybeT m a)’ 

ठीक है, तो Show व्युत्पत्ति के लिए MaybeT संभावना है क्योंकि नहीं था उस बाधा को अस्वीकार कर दिया गया होगा, क्योंकि यह प्रकार की बाधा है कि टाइपशेकर के बारे में समाप्त नहीं हो सकता है। आप इस जवाब में "इंस्टेंस हेड से छोटा नहीं" के बारे में और अधिक पढ़ सकते हैं: https://stackoverflow.com/a/17866970/176841

+1

लेकिन इसके दूसरे सुझाव, 'UndecidableInstances' को सक्षम करने के लिए, बिल्कुल ठीक है। – dfeuer

+0

इसलिए मैं संकलक को मेरे लिए उदाहरण प्राप्त करने के लिए 'UndecidableInstances' का उपयोग कर सकता हूं, लेकिन' हो सकता है 'प्रकार के बारे में क्या यह बिना किसी पहचान के अक्षम हो जाता है, जबकि यह' पहचान प्रकार 'प्रकार को ठीक से संभाल सकता है? पूर्व। मैं उम्मीद करता हूं कि यह बिना किसी एक्सटेंशन के 'होटटी [बस 1]' दिखाने में सक्षम होगा – robertjlooby

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