इस प्रश्न के उत्तर के लिए धन्यवाद मैंने एक प्रकार को इस प्रकार परिभाषित किया है:
data Chain = forall a. Integral a => Chain [[a]] [a] a a
यदि आप चाहें तो मुझे प्रत्येक फ़ील्ड, या तर्क के लिए गेटर फ़ंक्शन लिखना होगा। यहाँ मेरा पहला प्रयास है:
getSimplices (Chain simplices _ _ _) = simplices
लेकिन जब मैं ghc संकलित करने का प्रयास करता हूं तो निम्न त्रुटि देता है:
Chain.hs:10:40: error:
• Couldn't match expected type ‘t’ with actual type ‘[[a]]’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor:
Chain :: forall a. Integral a => [[a]] -> [a] -> a -> a -> Chain,
in an equation for ‘getSimplices’
at Chain.hs:10:15-35
• In the expression: simplices
In an equation for ‘getSimplices’:
getSimplices (Chain simplices _ _ _) = simplices
• Relevant bindings include
simplices :: [[a]] (bound at Chain.hs:10:21)
getSimplices :: Chain -> t (bound at Chain.hs:10:1)
मैंने इसे इस तरह ठीक किया:
getSimplices (Chain simplices _ _ _) = map (map fromIntegral) simplices
यहां तक कि अगर किसी प्रकार का जीएचसी जादू इसे गेट्टर के लिए अश्लील रूप से धीमा होने से रोकता है, तो मुझे लगता है कि इस तरह से कुछ ठीक करना सिर्फ अत्याचारी है। क्या इस तरह के प्रकारों के लिए गेटर्स को परिभाषित करने का कोई बेहतर तरीका है?
2 जवाब
आपके अनुसार getSimplices
किस प्रकार का होना चाहिए? "स्पष्ट" विकल्प है
getSimplices :: Integral a => Chain -> [[a]]
लेकिन यह आपके कार्यान्वयन के साथ काम नहीं करता है, क्योंकि getSimplices
के कॉलर को a
चुनने के लिए मिलता है, और इस बात की कोई गारंटी नहीं है कि Chain
में संग्रहीत मान उसी प्रकार के हैं जो कॉल करने वाला चाहता है, क्योंकि आपने वह जानकारी फेंक दी थी। विचार करना:
let c = Chain [[1 :: Int]] [2] 3 4
in (getSimplices c) :: [[Integer]]
यह आपके दो प्रकार के हस्ताक्षरों द्वारा स्पष्ट रूप से अनुमत है जो किसी भी इंटीग्रल प्रकार के लिए काम करने का वादा करते हैं, लेकिन स्पष्ट रूप से कुछ रूपांतरण के बिना काम नहीं कर सकते हैं: Int
को किसी तरह Integer
s में बदलना होगा।
जैसा कि टिप्पणियां कहती हैं, यह बल्कि असामान्य है। चेन में टाइप पैरामीटर जोड़ना बहुत आसान होगा, ताकि यह उस प्रकार को ट्रैक कर सके जिसे आपने इसे बनाने के लिए उपयोग किया था, और इसके आउटपुट को उस प्रकार तक भी सीमित कर दिया था:
data Chain a = Chain [[a]] [a] a a
getSimplices :: Chain a -> [[a]]
getSimplices (Chain xs _ _ _) = xs
एक अस्तित्वगत प्रकार का निर्माता आवश्यक रूप से a
के बारे में "भूल जाता है":
Chain :: Integral a => [[a]] -> [[a]] -> a -> a -> Chain
ध्यान दें कि कैसे परिणामी प्रकार अब a
पर निर्भर नहीं करता है।
इसका एक परिणाम यह है कि, जब हम Chain
पर पैटर्न मैच करते हैं, तो हम इस बारे में कोई धारणा नहीं बना सकते हैं कि a
क्या है। आखिर निर्माण करते समय हम कुछ भी चुन सकते थे। a
के बारे में हमारे पास एकमात्र ज्ञान यह है कि यह एक अभिन्न प्रकार होना चाहिए। इसलिए, हम केवल Integral
टाइप क्लास के तरीकों का उपयोग करके एक्सेस कर सकते हैं।
सामान्य नियम यह है कि, जब हम Chain
पर पैटर्न मैच करते हैं, तो हमें एक प्रकार का मान लौटाना होगा जो a
पर निर्भर नहीं है। एक गेट्टर लाइक
getter (Chain _ _ x _) = x
उस नियम का उल्लंघन करें। आखिर वह किस प्रकार का होगा?
getter :: Chain -> ???
पक्का नहीं
getter :: Chain -> a
इसके बजाय इसका मतलब यह होगा कि हम Chain
से अपनी इच्छानुसार कोई भी प्रकार निकाल सकते हैं। यह वास्तविक रूप से काम नहीं कर सकता है: हम यह चुनने के लिए स्वतंत्र नहीं हो सकते कि किस प्रकार को रखना है, और फिर यह चुनने के लिए भी स्वतंत्र हो सकते हैं कि किस प्रकार को निकालना है।
हालांकि, हम Integral
का फायदा उठाने के लिए क्या कर सकते हैं:
getter :: Chain -> Integer
getter (Chain _ _ x _) = fromIntegral x
Integer
a
पर निर्भर नहीं है, इसलिए यह ठीक है।
संबंधित सवाल
जुड़े हुए प्रश्न
नए सवाल
haskell
हास्केल एक कार्यात्मक प्रोग्रामिंग भाषा है जिसमें मजबूत स्थैतिक टाइपिंग, आलसी मूल्यांकन, व्यापक समानता और संक्षिप्तता समर्थन और अद्वितीय अमूर्त क्षमताओं की विशेषता है।