एक लाभ यह है कि डेटा परिवार इंजेक्शनिव हैं, परिवारों के विपरीत।
आप
type family TF a
data family DF a
है तो आप जानते हैं कि DF a ~ DF b
का तात्पर्य है कि a ~ b
, जबकि TF के साथ, तुम नहीं - किसी भी a
के लिए आप यह सुनिश्चित करें कि DF a
एक पूरी तरह से नए प्रकार (बस की तरह है हो सकता है [a]
[b]
से एक अलग प्रकार है, बेशक a ~ b
), जबकि एक प्रकार का परिवार एक ही मौजूदा प्रकार पर एकाधिक इनपुट प्रकारों को मानचित्र कर सकता है।
एक सेकंड यह है कि डेटा परिवारों को आंशिक रूप से लागू किया जा सकता है, किसी अन्य प्रकार के कन्स्ट्रक्टर की तरह, जबकि परिवार नहीं कर सकते हैं।
यह एक विशेष रूप से वास्तविक दुनिया उदाहरण नहीं है, लेकिन उदाहरण के लिए, आप कर सकते हैं:
data instance DF Int = DInt Int
data instance DF String = DString String
class C t where
foo :: t Int -> t String
instance C DF where -- notice we are using DF without an argument
-- notice also that you can write instances for data families at all,
-- unlike type families
foo (DInt i) = DString (show i)
असल में, DF
और DF a
किसी अन्य की तरह, वास्तविक, प्रथम श्रेणी, वैध प्रकार, अपने आप में कर रहे हैं टाइप करें data
के साथ घोषित करें। TF a
सिर्फ एक मध्यवर्ती रूप है जो एक प्रकार का मूल्यांकन करता है।
लेकिन मुझे लगता है कि यह सब बहुत प्रबुद्ध नहीं है, या कम से कम यह मेरे लिए नहीं था, जब मैं डेटा परिवारों के बारे में सोच रहा था और इसी तरह की चीजें पढ़ता था।
यहां अंगूठे का नियम है जिसे मैं जाता हूं। जब भी आप अपने आप को एक प्रकार का परिवार दोहराते हैं, और प्रत्येक इनपुट प्रकार के लिए, आप एक नए data
प्रकार को परिवार के मानचित्र पर टाइप करने के लिए घोषित करते हैं, तो बिचौलियों को काटने और इसके बजाय डेटा परिवार का उपयोग करने के लिए यह अच्छा है।
vector लाइब्रेरी से वास्तविक दुनिया का उदाहरण। vector
में कई अलग-अलग प्रकार के वेक्टर हैं: बॉक्स किए गए वैक्टर, अनबॉक्स किए गए वैक्टर, आदिम वैक्टर, स्टेबल वैक्टर। प्रत्येक Vector
प्रकार के लिए एक संबंधित, mutable MVector
प्रकार (सामान्य वेक्टर अपरिवर्तनीय हैं) टाइप करें। तो यह इस तरह दिखता है: बजाए किसी
type family Mutable v :: * -> * -> * -- the result type has two type parameters
module Data.Vector{.Mutable} where
data Vector a = ...
data MVector s a = ...
type instance Mutable Vector = MVector
module Data.Vector.Storable{.Mutable} where
data Vector a = ...
data MVector s a = ...
type instance Mutable Vector = MVector
[etc.]
अब, मैं नहीं बल्कि होगा:
data family Mutable v :: * -> * -> *
module Data.Vector{.Mutable} where
data Vector a = ...
data instance Mutable Vector s a = ...
type MVector = Mutable Vector
module Data.Vector.Storable{.Mutable} where
data Vector a = ...
data instance Mutable Vector s a = ...
type MVector = Mutable Vector
[etc.]
कौन सा अपरिवर्तनीय encodes ठीक एक Mutable Vector
प्रकार है कि वहाँ हर Vector
प्रकार के लिए, और है कि वहाँ उनके बीच एक-एक-एक पत्राचार। Vector
के उत्परिवर्तनीय संस्करण को हमेशा Mutable Vector
कहा जाता है: यह उसका नाम है, और इसमें कोई अन्य नहीं है। यदि आपके पास Mutable Vector
है, तो आप संबंधित अपरिवर्तनीय Vector
का प्रकार प्राप्त कर सकते हैं, क्योंकि यह एक प्रकार तर्क के रूप में ठीक है। type family Mutable
के साथ, एक बार जब आप इसे तर्क के लिए लागू करते हैं तो यह एक अनिर्दिष्ट परिणाम प्रकार का मूल्यांकन करता है (संभवतः MVector
कहा जाता है, लेकिन आप नहीं जानते), और आपके पास पीछे की ओर मानचित्र करने का कोई तरीका नहीं है।
केवल मौजूदा प्रकार की ओर इशारा करने के बजाय, कभी-कभी आप अपने स्वयं के ताजा प्रकार, एक मौजूदा एक को लपेटना चाहते हैं या सिर्फ विभिन्न क्षेत्रों के साथ एक सामान्य रिकॉर्ड रखना चाहते हैं, लेकिन मौजूदा में केवल एक बेकार समानार्थी नहीं। आप इन्हें उसी तरह उपयोग कर सकते हैं जैसे आप आमतौर पर 'डेटा' के साथ घोषित प्रकारों का उपयोग करते हैं, सिवाय इसके कि इस प्रकार के प्रतिनिधित्व के प्रकार के आधार पर प्रतिनिधित्व अलग-अलग होने जा रहा है। –