2016-09-26 18 views
13

अब हमारे पास इंजेक्शन प्रकार परिवार हैं, क्या परिवार परिवारों के प्रकार के परिवारों का उपयोग करने के लिए कोई शेष उपयोग केस है?डेटा परिवार बनाम इंजेक्शन प्रकार परिवार

डेटा परिवारों के बारे में पिछले StackOverflow सवाल को देखते हुए, वहाँ एक जोड़े साल पहले प्रकार परिवारों और डेटा परिवारों के बीच अंतर पर चर्चा से this question, और this answer डेटा परिवारों के उपयोग के मामलों के बारे में है। दोनों कहते हैं कि डेटा परिवारों की इंजेक्शनिटी उनकी सबसे बड़ी ताकत है।

docs on data families पर देखकर, मुझे injective type families का उपयोग कर डेटा परिवारों के सभी उपयोगों को फिर से लिखने का कारण नहीं दिखता है।

उदाहरण के लिए, मैं एक डेटा परिवार है का कहना है कि (मैं डॉक्स से कुछ उदाहरण विलय कर दिया गया है डेटा परिवारों की सभी सुविधाओं में निचोड़ करने की कोशिश करने के लिए)

data family G a b 
data instance G Int Bool = G11 Int | G12 Bool deriving (Eq) 
newtype instance G() a = G21 a 
data instance G [a] b where 
    G31 :: c -> G [Int] b 
    G32 :: G [a] Bool 

मैं भी

के रूप में यह फिर से लिखने सकता है
type family G a b = g | g -> a b 
type instance G Int Bool = G_Int_Bool 
type instance G() a = G_Unit_a a 
type instance G [a] b = G_lal_b a b 

data G_Int_Bool = G11 Int | G12 Bool deriving (Eq) 
newtype G_Unit_a a = G21 a 
data G_lal_b a b where 
    G31 :: c -> G_lal_b [Int] b 
    G32 :: G_lal_b [a] Bool 

यह कहने के बिना चला जाता है कि डेटा परिवारों के लिए संबंधित उदाहरण इसी प्रकार के परिवारों के साथ संबंधित उदाहरणों से मेल खाते हैं। फिर एकमात्र शेष अंतर है कि हमारे पास टाइप-नेमस्पेस में कम चीजें हैं?

एक फॉलोअप के रूप में, क्या टाइप-नेमस्पेस में कम चीजें रखने का कोई फायदा है? मैं सोच सकता हूं कि यह ghci पर किसी के साथ खेलने वाले किसी के लिए नरक डीबगिंग हो जाएगा - रचनाकारों के प्रकार सभी संकेत देते हैं कि रचनाकार सभी एक जीएडीटी के तहत हैं ...

+0

मैंने सोचा कि [यह] (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#constraints-in-kinds) डेटा परिवारों के साथ किया जा सकता है और प्रकार नहीं परिवार, लेकिन यह डेटा परिवारों के साथ भी काम नहीं करता है - आप ऐसे डेटा परिवार की घोषणा कर सकते हैं लेकिन किसी भी उदाहरण की घोषणा करने का प्रयास करने से त्रुटि होती है। – user2407038

+0

@ user2407038 मुझे यकीन नहीं है कि मैं समझता हूं - उदाहरण स्पष्ट रूप से प्रकार के परिवारों के साथ काम करता है (जैसा कि आपने जो लिंक दिया है), और मैं इसे डेटा परिवारों के साथ काम करने के लिए भी प्राप्त कर सकता हूं, लेकिन मुझे लाभ नहीं दिखाई देता है। ('डेटा परिवार टी :: ए -> *; डेटा उदाहरण टी 42 = एमकेएनएट; डेटा इंस्टेंस टी" घबराओ मत! "= एमकेसिंबोल') – Alec

+1

वे अलग-अलग प्रकार हैं; उपयोगकर्ता मार्गदर्शिका में उदाहरण * प्रकार * कन्स्ट्रक्टर (मूल्य कन्स्ट्रक्टर नहीं) में समानता बाधा ('IsTypeLit a ~ True') के बारे में है। आपको किसी प्रकार के परिवार के प्रकार पर कोई बाधा नहीं हो सकती है, और आप 'डेटा परिवार टी :: फॉरल ए घोषित कर सकते हैं। (IsTypeLit a ~ 'True) => a -> * 'लेकिन' टी' के किसी भी उदाहरण कभी नहीं। – user2407038

उत्तर

9
type family T a = r | r -> a 
data family D a 

एक injective प्रकार परिवार T संतुष्ट injectivity स्वयंसिद्ध

T a ~ T b तो a ~ b

लेकिन एक डेटा परिवार बहुत मजबूत generativity स्वयंसिद्ध

अगरको संतुष्ट करता हैतो D ~ g और a ~ b

(यदि आप चाहें:। क्योंकि D के उदाहरण नए प्रकार है कि किसी भी मौजूदा प्रकार से अलग हैं परिभाषित)

तथ्य D ही में प्रकार प्रणाली में एक वैध प्रकार है, T जैसे किसी प्रकार के परिवार के विपरीत, जो केवल T a जैसे पूर्णतः संतृप्त अनुप्रयोग में दिखाई दे सकता है। यह

  • D एक अन्य प्रकार के निर्माता के लिए तर्क, MaybeT D की तरह हो सकता है इसका मतलब है। (MaybeT T अवैध है।)

  • आप , instance Functor D जैसे उदाहरणों को परिभाषित कर सकते हैं। (आप किसी प्रकार के परिवार Functor T के लिए उदाहरण परिभाषित नहीं कर सकते हैं, और यह अनुपयोगी होगा क्योंकि उदाहरण के लिए उदाहरण map :: Functor f => (a -> b) -> f a -> f b इस तथ्य पर निर्भर करता है कि f a प्रकार से आप f और a दोनों निर्धारित कर सकते हैं; इसके लिए f काम नहीं कर सकता प्रकार परिवारों, यहां तक ​​कि injective लोगों के साथ बदल करने की अनुमति दी।)

+0

आह! यह वह टुकड़ा है जिसे मैं याद कर रहा था। बहुत बहुत धन्यवाद - यह वास्तव में जनरेटिविटी (और रिचर्ड ईसेनबर्ग के थीसिस में "मिलानशीलता" के बारे में बहुत भ्रम के साथ मिलकर समाप्त हो जाता है)। – Alec

4

आप एक दूसरे को याद कर रहे हैं विस्तार - डेटा परिवार नए प्रकार बनाते हैं। टाइप परिवार केवल अन्य प्रकारों को संदर्भित कर सकते हैं। विशेष रूप से, एक डेटा परिवार के हर उदाहरण नए रचनाकारों की घोषणा करता है। और यह अच्छी तरह से सामान्य है। यदि आप न्यूटाइप सेमेन्टिक्स चाहते हैं तो आप newtype instance के साथ डेटा इंस्टेंस बना सकते हैं। आपका उदाहरण एक रिकॉर्ड हो सकता है। इसमें कई रचनाकार हो सकते हैं। यदि आप चाहें तो यह एक जीएडीटी भी हो सकता है।

यह type और data/newtype कीवर्ड के बीच बिल्कुल अंतर है। इंजेक्शन प्रकार परिवार आपको नए प्रकार नहीं देते हैं, जहां आपको इसकी आवश्यकता होती है, उन्हें बेकार प्रदान करते हैं।

मैं समझता हूं कि आप कहां से आ रहे हैं। शुरुआत में अंतर के साथ मेरा यही मुद्दा था। तब मैं अंततः एक उपयोग मामले में भाग गया जहां वे उपयोगी हैं, यहां तक ​​कि एक प्रकार की कक्षा के बिना भी शामिल हो।

मैं कक्षाओं का उपयोग किए बिना कुछ अलग संदर्भों में म्यूटेबल कोशिकाओं से निपटने के लिए एक एपीआई लिखना चाहता था। मुझे पता था कि मैं इसे IO, ST में दुभाषियों के साथ एक मुक्त मोनैड के साथ करना चाहता था, और हो सकता है कि unsafeCoerce के साथ कुछ भयानक हैक्स भी State में शूहोर्निंग तक जाएं। यह किसी भी व्यावहारिक उद्देश्य के लिए नहीं था, बेशक - मैं सिर्फ एपीआई डिज़ाइन की तलाश कर रहा था।

data MutableEnv (s :: k) a ... 

newRef :: a -> MutableEnv s (Ref s a) 
readRef :: Ref s a -> MutableEnv s a 
writeRef :: Ref s a -> a -> MutableEnv s() 

MutableEnv की परिभाषा महत्वपूर्ण नहीं था:

तो मैं कुछ इस तरह था। एपीआई में तीन कार्यों से मेल खाने वाले रचनाकारों के साथ बस मानक मुक्त/परिचालन मोनड सामान।

लेकिन मैं रेफरी को परिभाषित करने के लिए क्या अटक गया था पर अटक गया था। मैं किसी प्रकार की कक्षा नहीं चाहता था, मैं चाहता था कि यह एक ठोस प्रकार हो जहां तक ​​टाइप सिस्टम का संबंध था।

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

data family Ref (s :: k) :: * -> * 

फिर, रेफरी के लिए अंतर्निहित प्रतिनिधित्व से निपटना कोई बड़ा सौदा नहीं था। जब भी MutableEnv के लिए एक दुभाषिया परिभाषित किया जाता है तो बस एक डेटा इंस्टेंस (या न्यूटाइप इंस्टेंस, अधिक संभावना) बनाएं।

यह सटीक उदाहरण वास्तव में उपयोगी नहीं है। लेकिन यह स्पष्ट रूप से कुछ डेटा परिवारों को दिखाता है कि इंजेक्शन प्रकार परिवार नहीं कर सकते हैं।

+0

धन्यवाद, यह एक बहुत ही रोचक उदाहरण है (वास्तव में मुझे यह देखना अच्छा लगेगा कि आप इन विचारों के साथ कहां समाप्त हुए)! उस ने कहा, मुझे अभी भी यकीन नहीं है कि मैं एक तकनीकी परिप्रेक्ष्य से देखता हूं कि क्यों 'रेफरी' एक प्रकार का परिवार नहीं हो सकता था (संभवतः, हालांकि जरूरी नहीं) प्रत्येक उदाहरण के लिए एक नया 'डेटा' या 'न्यूटाइप' के साथ। – Alec

+0

कुछ स्तर पर, डेटा परिवार और नियमित प्रकार के परिवार के बीच कोई अंतर नहीं है, सिवाय इसके कि डेटा परिवार द्वारा इंगित डेटा प्रकारों के पास कोई अन्य नाम नहीं है। ऐसा नहीं है कि आप विभिन्न डेटा उदाहरणों या कुछ से रचनाकारों पर जीएडीटी-जैसे पैटर्न मिलान कर सकते हैं। कभी-कभी, आप बस यह लागू करना चाहते हैं कि डेटा परिवार का नाम इस प्रकार का एकमात्र नाम है, हालांकि। – Carl

+0

वैसे यह इस सवाल का मुद्दा है - मुझे इतना यकीन नहीं है कि डेटा परिवारों के बीच कोई अंतर नहीं है और परिवारों + डेटा/न्यूटाइप घोषणाएं टाइप करें। मुझे संदेह है कि आंखों की तुलना में यहां कुछ और है। – Alec

3

answer by Reid Barton पूरी तरह से मेरी दो उदाहरण के बीच अंतर बताते हैं। इसने मुझे रिचर्ड ईसेनबर्ग के thesis में हास्केल पर निर्भर प्रकार जोड़ने के बारे में कुछ याद दिलाया है और मैंने सोचा था कि चूंकि इस प्रश्न का दिल इंजेक्शन और जनरेटिविटी है, यह उल्लेखनीय होगा कि DependentHaskell इस से निपटने के लिए कैसे होगा (जब यह अंततः लागू हो जाता है , और यदि अब प्रस्तावित क्वांटिफायर अंततः लागू किए गए हैं)।

पृष्ठ 56 और 57 (4.3) पर आधारित है।ऊपर उल्लिखित thesis के 4 Matchability):

परिभाषा (generativity) f और g उत्पादक हैं, तो f a ~ g b तात्पर्य f ~ g

परिभाषा (Injectivity) तो f injective है, तो f a ~ f b तात्पर्य a ~ b

परिभाषा (Matchability) एक समारोह f तुलनीय है iff यह उत्पादक है और injective

हास्केल में के रूप में हम यह अब पता (8.0.1) तुलनीय (प्रकार-स्तर) कार्यों newtype, डेटा की वास्तव में मिलकर बनता है, और डेटा परिवार कन्स्ट्रक्टर टाइप करें। भविष्य में, DependentHaskell के तहत, हमें प्राप्त होने वाले नए क्वांटिफायरों में से एक '-> होगा और इसका उपयोग मिलान करने योग्य कार्यों को दर्शाने के लिए किया जाएगा। दूसरे शब्दों में, कंपाइलर को सूचित करने का एक तरीका होगा एक प्रकार-स्तरीय फ़ंक्शन जेनरेटिव होता है (जो वर्तमान में केवल यह सुनिश्चित करके किया जा सकता है कि फ़ंक्शन एक प्रकार का कन्स्ट्रक्टर है)।

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