2012-10-25 12 views
6

इस कोड को सहीमैं इस अपरिवर्तित प्रकार के साथ उदाहरण क्यों नहीं बना सकता?

instance Functor IO where -- note that IO isn't parametrized, and it's correct 
    fmap f action = do 
     result <- action 
     return (f result) 

लेकिन निम्नलिखित कोड एक संकलक त्रुटि है क्यों है?

class Print a where 
    print :: a -> String 

data A t = A t 
instance Print A where -- error: expecting one more argument to `A' 
    print a = "abc" 

उत्तर

10

ऐसा इसलिए है क्योंकि kinds मेल नहीं खाते। नियमित प्रकारों में * है, जबकि टाइपर्स जैसे A या IO में * -> * है, यह दर्शाता है कि उन्हें एक प्रकार को वापस करने के लिए एक प्रकार पैरामीटर की आवश्यकता है।

Print वर्ग की परिभाषा में, संकलक infers कि के बाद से a एक सादे प्रकार के रूप में प्रयोग किया जाता है, यह एक तरह * होना आवश्यक है। हालांकि, तरह * -> * के प्रकार के निर्माताओं पर Functor काम करता है:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

यहाँ, f एक सादे प्रकार के रूप में प्रयोग नहीं किया जाता है, लेकिन एक प्रकार निर्माता के रूप में है, तो यह एक तरह का अनुमान लगाया है * -> * है। आप GHCi में :kind आदेश के साथ इस की पुष्टि कर सकते हैं:

> :kind Print 
Print :: * -> Constraint 
> :kind Functor 
Functor :: (* -> *) -> Constraint 
9

जब आप कहते हैं कि

class Print a where 
    print' :: a -> String 

आप यह सुनिश्चित करें कि a एक प्रकार हो गया है, लेकिन जब आप कहते हैं

data A t = A t 

आप A एक प्रकार निर्माता बनाने - A नहीं है एक प्रकार, लेकिन A Int उदाहरण के लिए है। A प्रकारों पर एक प्रकार का फ़ंक्शन है, लेकिन प्रिंट क्लास में a एक प्रकार का मान होना चाहिए, एक प्रकार का फ़ंक्शन नहीं।

आप

instance Print (A Int) where 
    print' a = "abc" 

कर सकता है क्योंकि Functor वर्ग एक प्रकार निर्माता के लिए पूछता है यह IO के लिए ठीक है।

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

आप देख सकते हैं कि जब f a एक प्रकार है, f एक प्रकार निर्माता है, जैसे IO और A हैं। आप

instance Functor A where -- OK, A is a constructor, Functor needs one 
    fmap f (A x) = A (f x) 

करने में सक्षम हो जाएगा और आप

instance Eq IO where -- not OK - IO is a constructor and Eq needs a type 
    (==) = error "this code won't compile" 

ऐसा करने में सक्षम नहीं होगा (मैं print' बजाय print का उपयोग किया है मानक समारोह print के साथ संघर्ष से बचने के लिए।)

1

मानसिक रूप से प्रयास करें (या एक पाठ संपादक के साथ) प्रकार आप उदाहरण में उपयोग किया है के साथ वर्ग परिभाषा में दिए गए प्रकार में भरने।

से:

class Print a where 
    print :: a -> String 

और

data A t = A t 

हम

instance Print A 

तो चाहते हैं, A हम कह रहे हैं के लिए प्रकार वर्ग परिभाषा a प्रतिस्थापन एक instnace है, हमें यह मिलता है:

class Print A where 
    print :: A -> String 

उह-ओह। A -> String एक प्रकार के रूप में समझ में नहीं आता है, क्योंकि फ़ंक्शन प्रकार तीर बाईं ओर एक प्रकार और दाईं ओर एक प्रकार लेता है, और आपको फ़ंक्शन प्रकार देता है। लेकिन A एक प्रकार नहीं है, क्योंकि आपने को data A t के साथ घोषित किया है; A t किसी भी प्रकार के t के लिए एक प्रकार है, लेकिन A एक प्रकार का निर्माता है। यदि आप इसे किसी प्रकार पर लागू करते हैं तो यह एक प्रकार का बना सकता है, लेकिन A स्वयं कुछ अलग है। तो आप Print के उदाहरण में A t बना सकते हैं, लेकिन A स्वयं नहीं।

तो instance Functor IO क्यों काम किया? चलो वर्ग परिभाषा को देखो:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

अब f के लिए IO प्रतिस्थापन की कोशिश कर सकते हैं:

class Functor IO where 
    fmap :: (a -> b) -> IO a -> IO b 

IO अंत तक मापदंडों टाइप करने के लिए लागू किया जाता है, तो यह सब बाहर काम करता है। अगर हम Int या A t जैसेका एक ठोस प्रकार बनाने की कोशिश करते हैं तो हम समस्याओं में भाग लेंगे।

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