Haskell Language
प्रकार के परिवार
खोज…
टाइप पर्यायवाची परिवार
टाइप पर्यायवाची परिवार केवल टाइप-स्तरीय फ़ंक्शन हैं: वे पैरामीटर प्रकारों को परिणाम प्रकारों के साथ जोड़ते हैं। ये तीन अलग-अलग किस्मों में आते हैं।
बंद प्रकार-समानार्थी परिवार
ये सामान्य मूल्य-स्तरीय हास्केल कार्यों की तरह काम करते हैं: आप कुछ खंड निर्दिष्ट करते हैं, कुछ प्रकारों को मैप करते हैं:
{-# LANGUAGE TypeFamilies #-}
type family Vanquisher a where
Vanquisher Rock = Paper
Vanquisher Paper = Scissors
Vanquisher Scissors = Rock
data Rock=Rock; data Paper=Paper; data Scissors=Scissors
खुले प्रकार-समानार्थी परिवार
ये टाइपकास्ट उदाहरणों की तरह अधिक काम करते हैं: कोई भी अन्य मॉड्यूल में अधिक खंड जोड़ सकता है।
type family DoubledSize w
type instance DoubledSize Word16 = Word32
type instance DoubledSize Word32 = Word64
-- Other instances might appear in other modules, but two instances cannot overlap
-- in a way that would produce different results.
वर्ग-संबद्ध प्रकार के समानार्थक शब्द
एक खुले प्रकार के परिवार को एक वास्तविक वर्ग के साथ भी जोड़ा जा सकता है। यह आमतौर पर किया जाता है, के साथ की तरह है संबद्ध डेटा परिवारों , कुछ वर्ग विधि अतिरिक्त सहायता तत्व की जरूरत है, और इन सहायता तत्व विभिन्न उदाहरणों के लिए अलग हो सकता है लेकिन संभवतः भी साझा कर सकते हैं। एक अच्छा उदाहरण VectorSpace
क्लास है :
class VectorSpace v where
type Scalar v :: *
(*^) :: Scalar v -> v -> v
instance VectorSpace Double where
type Scalar Double = Double
μ *^ n = μ * n
instance VectorSpace (Double,Double) where
type Scalar (Double,Double) = Double
μ *^ (n,m) = (μ*n, μ*m)
instance VectorSpace (Complex Double) where
type Scalar (Complex Double) = Complex Double
μ *^ n = μ*n
ध्यान दें कि पहले दो उदाहरणों में, Scalar
का कार्यान्वयन समान है। यह एक संबद्ध डेटा परिवार के साथ संभव नहीं होगा: डेटा परिवार इंजेक्टिव हैं , टाइप-समानार्थी परिवार नहीं हैं।
जबकि गैर-इंजेक्टिविटी ऊपर की तरह कुछ संभावनाएं खोलती है, यह टाइप इंफ़ेक्शन को और अधिक कठिन बना देती है। उदाहरण के लिए, निम्नलिखित टाइप नहीं करेगा:
class Foo a where
type Bar a :: *
bar :: a -> Bar a
instance Foo Int where
type Bar Int = String
bar = show
instance Foo Double where
type Bar Double = Bool
bar = (>0)
main = putStrLn (bar 1)
इस मामले में, कंपाइलर को यह पता नहीं चल सकता है कि किस उदाहरण का उपयोग करना है, क्योंकि bar
का तर्क अपने आप में केवल एक बहुरूपी Num
शाब्दिक है। और प्रकार समारोह Bar
, 'उलटी दिशा "में हल नहीं किया जा सकता है ठीक है क्योंकि यह injective नहीं है † और इसलिए उलटी नहीं (वहाँ के साथ अधिक से अधिक एक प्रकार हो सकता है Bar a = String
)।
† केवल इन दो उदाहरणों के साथ, यह वास्तव में injective है, लेकिन संकलक किसी पर बाद में अधिक उदाहरण नहीं जोड़ देगा और इस तरह व्यवहार बाधित नहीं जान सकते।
डेटाटाइप परिवार
डेटा परिवारों का उपयोग डेटाटाइप बनाने के लिए किया जा सकता है, जिनके प्रकार तर्क के आधार पर अलग-अलग कार्यान्वयन हैं।
स्टैंडअलोन डेटा परिवार
{-# LANGUAGE TypeFamilies #-}
data family List a
data instance List Char = Nil | Cons Char (List Char)
data instance List () = UnitList Int
उपरोक्त घोषणा में, Nil :: List Char
, और UnitList :: Int -> List ()
संबद्ध डेटा परिवार
डेटा परिवार टाइपकास्ट के साथ भी जुड़े हो सकते हैं। यह अक्सर "हेल्पर ऑब्जेक्ट्स" के प्रकार के लिए उपयोगी होता है, जो जेनेरिक टाइपकास्ट के तरीकों के लिए आवश्यक होते हैं, लेकिन ठोस उदाहरण के आधार पर अलग-अलग जानकारी शामिल करने की आवश्यकता होती है। उदाहरण के लिए, किसी सूची में स्थानों को सूचीबद्ध करने के लिए केवल एक संख्या की आवश्यकता होती है, जबकि एक पेड़ में आपको प्रत्येक नोड पर पथ को इंगित करने के लिए एक नंबर की आवश्यकता होती है:
class Container f where
data Location f
get :: Location f -> f a -> Maybe a
instance Container [] where
data Location [] = ListLoc Int
get (ListLoc i) xs
| i < length xs = Just $ xs!!i
| otherwise = Nothing
instance Container Tree where
data Location Tree = ThisNode | NodePath Int (Location Tree)
get ThisNode (Node x _) = Just x
get (NodePath i path) (Node _ sfo) = get path =<< get i sfo
Injectivity
जरूरी नहीं कि टाइप फैमिलीज इंजेक्टिव हों। इसलिए, हम किसी एप्लिकेशन से पैरामीटर का अनुमान नहीं लगा सकते हैं। उदाहरण के लिए, में servant
, एक प्रकार दिया Server a
हम प्रकार अनुमान नहीं लगा सकता a
। इस समस्या को हल करने के लिए, हम Proxy
उपयोग कर सकते हैं। उदाहरण के लिए, servant
, serve
का प्रकार होता है ... Proxy a -> Server a -> ...
हम अनुमान लगा सकते हैं a
से Proxy a
क्योंकि Proxy
द्वारा परिभाषित किया गया data
जो injective है।