2011-11-04 9 views
17

निम्न प्रकारों पर विचार करें:क्या किसी प्रकार का वर्ग एक उदाहरण बनाना संभव है यदि उसके प्रकार पैरामीटर गलत क्रम में हैं?

data SomeType m a = SomeType (m Integer) [a] 

हम आसानी से निम्न कोड के साथ फ़ंक्शन का उदाहरण बना सकते हैं:

instance Functor (SomeType m) where 
    fmap f (SomeType m lst) = SomeType m (map f lst) 

हालांकि, यदि SomeType प्रकार के पैरा को स्वैप किया गया था:

data SomeType2 a m = SomeType2 (m Integer) [a] 

फिर उपर्युक्त उदाहरण परिभाषा काम नहीं करती है।

क्या SomeType2 को फ़ंक्शन का उदाहरण बनाने का कोई तरीका है? यदि नहीं, तो क्या हैकेल/ghc में कोई अप और आने वाले जोड़ हैं जो इसे संभव बना देंगे?

उत्तर

20

पूर्वाग्रह मैं हूं, लेकिन मुझे लगता है कि यह Control.Newtype का उपयोग करने का एक शानदार अवसर है, किट का एक छोटा टुकड़ा जो केवल "कैबल इंस्टॉल न्यूटाइप" दूर है।

यहां सौदा है। आप एक अलग पैरामीटर में functoriality (उदाहरण के लिए) पर अपने हाथ पाने के लिए चारों ओर कन्स्ट्रक्टरों के चारों ओर फ्लिप करना चाहते हैं। एक newtype

newtype Flip f x y = Flip (f y x) 

परिभाषित करें और Newtype वर्ग इस प्रकार

instance Newtype (Flip f x y) (f y x) where 
    pack = Flip 
    unpack (Flip z) = z 

Newtype वर्ग उनके सरल समकक्ष करने के लिए सिर्फ एक निर्देशिका मानचित्रण newtypes, आसान किट प्रदान कर रहा है, उदाहरण के लिए इसे जोड़ने op FlipFlip के विपरीत है: आपको इसे याद रखने की आवश्यकता नहीं है जिसे आपने इसे कहा था।

प्रश्न में समस्या के लिए, हम अब इस तरह सामान कर सकते हैं:

data Bif x y = BNil | BCons x y (Bif x y) deriving Show 

एक दो पैरामीटर डेटाप्रकार जो दोनों मानकों में functorial होने वाला है यही कारण है कि। (शायद, हम इसे एक Bifunctor वर्ग का एक उदाहरण बनाना चाहिए, लेकिन वैसे भी ...) हम इसे एक Functor दो बार से अधिक कर सकते हैं: पिछले पैरामीटर के लिए एक बार ...

instance Functor (Bif x) where 
    fmap f BNil = BNil 
    fmap f (BCons x y b) = BCons x (f y) (fmap f b) 

... और एक बार के लिए पहली:

instance Functor (Flip Bif y) where 
    fmap f (Flip BNil) = Flip BNil 
    fmap f (Flip (BCons x y b)) = Flip (BCons (f x) y (under Flip (fmap f) b)) 

जहां under p f एक साफ रास्ता op p . f . p कहने के लिए है।

मैं आपको कोई झूठ नहीं बताता: आज़माएं।

someBif :: Bif Int Char 
someBif = BCons 1 'a' (BCons 2 'b' (BCons 3 'c' BNil)) 

और फिर हम

*Flip> fmap succ someBif 
BCons 1 'b' (BCons 2 'c' (BCons 3 'd' BNil)) 
*Flip> under Flip (fmap succ) someBif 
BCons 2 'a' (BCons 3 'b' (BCons 4 'c' BNil)) 

इन परिस्थितियों में मिलता है, वहाँ वास्तव में कई मायनों एक ही बात एक Functor के रूप में देखा जा सकता है, तो यह सही है कहने के लिए कुछ शोर करना है कि हम जो जिस तरह से हमारा मतलब है। लेकिन अगर आप इसके बारे में व्यवस्थित हैं तो शोर इतना ज्यादा नहीं है।

+0

नया प्रकार बहुत अच्छा है। यह इन पैकेजों में से एक है, जहां मैंने पहली बार इसे देखा, मैं चाहता था कि मैं इसे अपने पिछले पिछले काम में उपयोग करने के लिए जानूंगा। –

+0

हालांकि यह अच्छा है और काम करता है, यह वास्तव में प्रश्न का उत्तर नहीं देता है क्योंकि आप अभी भी कुछ टाइप 2 के लिए फ़ैक्टर का उदाहरण नहीं बना सकते हैं (और केवल 'अंडर' रैपर फ़ंक्शन के बिना fmap का उपयोग करें)। – ivanm

+2

मूल प्रश्न का उत्तर "नहीं" है। या कम से कम, हास्केल में नहीं। कुछ हद तक, यह काम करने के लिए असाधारण होगा कि उत्तर "हां" था। – pigworker

3

यह संभव नहीं है, और मुझे नहीं लगता कि यह किसी भी समय जल्दी ही हो जाएगा।

प्रकार पैरामीटर का क्रम इस प्रकार महत्वपूर्ण है। अंतिम मूल्य वह है जिसे आप फेंक्टर, आदि के साथ उपयोग के लिए "शामिल" करने जा रहे हैं।

मैंने इस प्रकार को एक प्रकार के समानार्थी परिभाषित करके काम करने की कोशिश की जो टाइप पैरामीटर को चारों ओर फिसल गया और फिर TypeSynonymInstances एक्सटेंशन का उपयोग किया, लेकिन यह काम करने में विफल रहा।

3

आप newtype रैपर का उपयोग कर सकते हैं जो प्रकार पैरामीटर को स्वैप करता है। लेकिन फिर आपको एक नया प्रकार मिलता है, और आपको अपने कोड में मूल और लपेटा प्रकार का अंतर बनाना होगा।

2

बेवकूफ उत्तर जो आप पहले ही जानते थे वह है: अपने पैरामीटर को फ़्लिप करें!

जीएचसी के लिए किसी भी अतिरिक्त लपेटने के बिना इस तरह की चीज का समर्थन करने के लिए, आपको टाइप-लेवल लैम्ब्डा जैसे कुछ की आवश्यकता होगी, जो शायद जल्द ही कभी भी नहीं जोड़ा जा रहा है। (मुझे लगता है कि के बारे में गलत साबित हो अच्छा लगेगा)

instance Functor (\a -> SomeType2 a m) where 
    -- fmap :: (a -> b) -> SomeType2 a m -> SomeType2 b m 
    fmap f (SomeType2 lst m) = SomeType (map f lst) m 

हम पहले से ही TypeSynonymInstances है के बाद से, हम कभी नहीं की तुलना में कुछ समय से थोड़ा जल्दी PartiallyAppliedTypeSynonymInstances के लिए आशा कर सकता है।

type SomeType3 m a = SomeType2 a m 

instance Functor (SomeType m) where 
    -- fmap :: (a -> b) -> SomeType3 m a -> SomeType3 m b 
    -- or, synonymously: 
    -- fmap :: (a -> b) -> SomeType2 a m -> SomeType2 a m 
    fmap f (SomeType2 lst m) = SomeType (map f lst) m 
+1

मान लीजिए कि आपके पास PartiallyAplpliedTypeSynonymInstances हैं, और 'टाइप टी ए = इंटेगर' को परिभाषित करें। फिर हमें 'उदाहरण फंक्शन टी कहां सक्षम होना चाहिए जहां fmap _ x = x'। तो स्पष्ट रूप से गलत कोड कहने के लिए बहुत कठिन है 'fmap (+ 1) 7' चेक टाइप नहीं करना चाहिए! (यहां तक ​​कि उन मामलों में जहां आप बेवकूफ उदाहरण परिभाषित नहीं करते हैं, आप प्रकार के सभी प्रकार के कठिन अनुमान बना रहे हैं) –

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