मैं स्ट्रिंग को एक टाइपकास्ट का उदाहरण क्यों नहीं बना सकता हूं?


85

दिया :

data Foo =
  FooString String
class Fooable a where --(is this a good way to name this?)
  toFoo :: a -> Foo

मैं इसका Stringएक उदाहरण बनाना चाहता हूं Fooable:

instance Fooable String where
  toFoo = FooString

GHC फिर शिकायत करता है:

Illegal instance declaration for `Fooable String'
    (All instance types must be of the form (T t1 ... tn)
     where T is not a synonym.
     Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Fooable String'

अगर इसके बजाय मैं उपयोग करता हूं [Char]:

instance Fooable [Char] where
  toFoo = FooString

GHC शिकायतें:

Illegal instance declaration for `Fooable [Char]'
   (All instance types must be of the form (T a1 ... an)
    where a1 ... an are type *variables*,
    and each type variable appears at most once in the instance head.
    Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Fooable [Char]'

प्रश्न :

  • मैं एक टाइपकास्ट का स्ट्रिंग और उदाहरण क्यों नहीं बना सकता हूं?
  • यदि मैं अतिरिक्त ध्वज जोड़ता हूं, तो जीएचसी मुझे इससे दूर जाने के लिए तैयार है। यह एक अच्छा विचार है?

6
यह इस तरह के सवाल हैं जिन्हें मैं पसंद करता हूं और पसंदीदा के रूप में चिह्नित करता हूं क्योंकि अन्यथा मैं निकट भविष्य में जानता हूं कि मैं यह पूछ रहा हूं;)
ऑस्कर मेडेरोस

3
अतिरिक्त ध्वज के बारे में: यह संभवतः एक अच्छा विचार है, जब तक आप जीएचसी पर भरोसा करते हैं और समझते हैं कि झंडा क्या करता है। यसोद के दिमाग में आता है: यह आपको प्रोत्साहित करता है कि यसोड एप्लिकेशन लिखते समय हमेशा ओवरलोडेड स्प्रिंग्स प्राग्मा का उपयोग करें, और क्वॉडक्वाट्स यसोड रूटिंग नियमों के लिए एक आवश्यकता है। ध्यान दें कि संकलित समय पर एक ध्वज के बजाय, आप {-# LANGUAGE FlexibleInstances #-}अपने .ht फ़ाइल के शीर्ष पर (या किसी अन्य प्राग) को भी रख सकते हैं ।
डैन बर्टन

जवाबों:


65

ऐसा इसलिए है क्योंकि Stringयह केवल एक प्रकार का उपनाम है [Char], जो केवल प्रकार []पर टाइप कंस्ट्रक्टर का अनुप्रयोग है Char, इसलिए यह फ़ॉर्म का होगा ([] Char)। जो कि प्रकार का नहीं है (T a1 .. an)क्योंकि Charएक प्रकार का चर नहीं है।

इस प्रतिबंध का कारण अतिव्यापी उदाहरणों को रोकना है। उदाहरण के लिए, मान लें कि आपके पास एक था instance Fooable [Char], और फिर बाद में किसी ने साथ आकर परिभाषित किया instance Fooable [a]। अब संकलक यह पता लगाने में सक्षम नहीं होगा कि आप किसका उपयोग करना चाहते हैं, और आपको एक त्रुटि देगा।

उपयोग करके -XFlexibleInstances, आप मूल रूप से कंपाइलर को वादा कर रहे हैं कि आप ऐसे किसी भी उदाहरण को परिभाषित नहीं करेंगे।

आप जो पूरा करने की कोशिश कर रहे हैं, उसके आधार पर, रैपर को परिभाषित करना बेहतर हो सकता है:

newtype Wrapper = Wrapper String
instance Fooable Wrapper where
    ...

4
चलो तर्क के लिए कहते हैं कि मैं वास्तव में भी चाहता था instance Fooable [a]। वहाँ एक तरह से toFooकार्य करने का एक तरीका है अगर aएक चार है?
जॉन एफ। मिलर

7
@ जॉन: एक एक्सटेंशन है -XOverlappingInstancesजो इसे अनुमति देगा, और सबसे विशिष्ट उदाहरण उठाएगा । विवरण के लिए GHC उपयोगकर्ता का मार्गदर्शिका देखें
हमर

18

आप क्लासिक Haskell98 टाइपसेकल्स की दो सीमाओं में चल रहे हैं:

  • वे उदाहरणों में समानार्थक शब्द को अस्वीकार करते हैं
  • वे नेस्टेड प्रकारों को अस्वीकार करते हैं जो बदले में प्रकार चर नहीं रखते हैं।

इन प्रतिबंधों को दो भाषा एक्सटेंशन द्वारा हटा दिया गया है:

  • -XTypeSynonymInstances

जो आपको टाइप सिनॉयम्स (जैसे के Stringलिए [Char]) और:

  • -XFlexibleInstances

उदाहरण के प्रकारों पर प्रतिबंध को उठाते हैं T a b ..जहां पैरामीटर प्रकार के चर होते हैं। -XFlexibleInstancesध्वज उदाहरण घोषणा के सिर मनमाना नेस्टेड प्रकार का उल्लेख करने के लिए अनुमति देता है।

ध्यान दें कि इन प्रतिबंधों को उठाने से कभी-कभी अतिव्यापी उदाहरण हो सकते हैं , जिस बिंदु पर अस्पष्टता को हल करने के लिए एक अतिरिक्त भाषा एक्सटेंशन की आवश्यकता हो सकती है, जिससे जीएचसी आपके लिए एक उदाहरण चुन सकता है।


संदर्भ :


4

अधिकांश मामलों में FlexibleInstances एक अच्छा जवाब नहीं है। बेहतर विकल्प स्ट्रिंग को न्यूटाइप में लपेट रहे हैं या एक सहायक वर्ग की तरह पेश करते हैं:

class Element a where
   listToFoo :: [a] -> Foo

instance Element Char where
   listToFoo = FooString

instance Element a => Fooable [a] where
   toFoo = listToFoo

इसे भी देखें: http://www.haskell.org/haskellwiki/List_instance


2

इन उत्तरों को जोड़ते हुए, यदि आप प्रतिबंधों को उठाने में सहज नहीं हैं, तो ऐसे मामले हो सकते हैं जहां यह आपके स्ट्रिंग को एक नए स्वरूप में लपेटने के लिए समझ में आता है, जो एक वर्ग का एक उदाहरण हो सकता है। ट्रेडऑफ़ आपके कोड में लपेटने और अनचाहे रखने के लिए संभावित कुरूपता होगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.