2011-07-19 13 views
9

है निम्न प्रकार स्तरीय विचार करें:2 मानकों के साथ प्रकार के लिए प्रकार स्तरीय उदाहरण है जब प्रकार श्रेणी केवल एक

class Listable a where 
    asList :: a t -> [t] 

यह बहुत आसान एक पैरामीटर के साथ प्रकार के लिए उदाहरण बना दी गई है:

instance Listable [] where 
    asList = id 

instance Listable Maybe where 
    asList (Just x) = [x] 
    asList Nothing = [] 

अब मैं दो समान प्रकार के पैरामीटर के साथ एक जोड़ी के लिए एक उदाहरण कैसे बनाऊंगा?

data V2 a = V2 a a 

v2 (p,q) = V2 p q 

instance Listable V2 where 
    asList (V2 p q) = [p,q] 

अब मैं asList $ v2 (47, 11) तरह बातें लिख सकता है, लेकिन हार के इस प्रकार उद्देश्य: बेशक मैं कुछ रैपिंग कर सकता है।

क्या युग्म के प्रकार को उन मामलों में सीमित करने का कोई तरीका है जहां दोनों प्रकार के पैरामीटर बराबर हैं, और इसके लिए Listable उदाहरण लिखना है? यदि नहीं, तो सामान्य कामकाज क्या है?

उत्तर

13

तरीके इस धारणात्मक करना है, के बहुत सारे हैं। दुर्भाग्यवश, उनमें से अधिकतर वास्तव में काम नहीं करते हैं। अफसोस!

सबसे पहले, एक कार्यात्मक प्रोग्रामर के रूप में, मैं दांव लगाना चाहते यह है कि क्या आप वास्तव में लिखना चाहते हैं:

instance Listable (\a -> (a, a)) where 
    asList (p, q) = [p,q] 

दुर्भाग्य से टाइप स्तरीय lambdas मौजूद नहीं हैं। ,

type Same2 f a = f a a 

instance Listable (Same2 (,)) where { ... } 

कि या तो अनुमति नहीं है क्योंकि प्रकार पर्याय पूरी तरह से लागू नहीं किया है: हम ऊपर लैम्ब्डा एक प्रकार पर्याय उपयोग करने का एक नामित संस्करण लिख सकते हैं। हम बजाय एक अतिरिक्त तर्क यह है कि वर्णन होगा कैसे प्रकार चर लागू करने के लिए ले जा रहा प्रकार वर्ग कल्पना कर सकता: यहां तक ​​कि क्या app हो सकता है के बारे में सोच के बिना

class Listable app f where 
    asList :: app f a -> [a] 

instance Listable __ Maybe where { ... } 

instance Listable __ (,) where { ... } 

, यह भी विफल रहता है क्योंकि हम के लिए एक सुसंगत तरह की जरूरत नहीं है f पैरामीटर।

वास्तव में काम करने वाली चीज़ों पर आगे बढ़ना, मुझे लगता है कि newtype के अंदर प्रकार समानार्थी दृष्टिकोण को लपेटना सबसे आम तरीका है, फिर केवल रैपिंग और अनैपिंग के साथ सौदा करें।

newtype Same2 f a = Same2 (f a a) 

instance Listable (Same2 (,)) where { ... } 

यह थोड़ा बदसूरत है, तो यह काम करने योग्य है। आप इस तरह के कन्स्ट्रक्टर संरचना और अन्य खिलौने को इस प्रकार परिभाषित भी कर सकते हैं, फिर हूप-कूदिंग बॉयलरप्लेट के ढेर के नीचे दफन किए गए टाइप-स्तरीय पॉइंट-मुक्त अभिव्यक्तियों के साथ पागल हो जाएं।

एक अंतिम दृष्टिकोण के रूप में, आप भी "रिवर्स में" ऊपर लैम्ब्डा शैली दृष्टिकोण सांकेतिक शब्दों में बदलना कर सकते हैं, से जा रहा पूरी तरह से लागू किया संस्करण, एक प्रकार पैरामीटर के लिए:

class Listable t where 
    type ListableElem t :: * 
    asList :: t -> [ListableElem t] 

होने के नाते इस प्रकार की चीज करने में सक्षम परिवारों के प्रकार के लिए मुख्य प्रेरणा है। एमपीटीसी और फंडप के साथ भी यही बात व्यक्त की जा सकती है, लेकिन यह 1) समतुल्य और 2) बहुत अधिक है, इसलिए मैं इसे लिखने से परेशान नहीं करूंगा।

+0

इसे आज़माने के लिए आलसी होने के लिए खेद है, लेकिन अंतिम दृष्टिकोण 'इंस्टेंस लिस्टेबल (ए, ए)' की अनुमति देगा - है ना? – yatima2975

+0

@ yatima2975: बाहरी उदाहरण के रूप में '(,) 'के साथ अलग-अलग उदाहरण होने की कीमत पर, हां। शायद इसे मेरे उत्तर में एक उदाहरण के रूप में रखना चाहिए था, अब आप इसका जिक्र करते हैं ... –

2

आप यह करने के लिए कुछ आवरण प्रकार को परिभाषित करने के लिए है। (आप हालांकि newtype उपयोग करना चाहिए।) तुम भी परिभाषित कर सकता है:

newtype Foo t a = Foo(t a a) 

instance Listable (Foo (,)) where 
    asList (Foo (a,b)) = [a,b] 
संबंधित मुद्दे