गणेश ने कहा, आप वास्तव में अधिक प्रकार की सुरक्षा के लिए जीएडीटी का उपयोग कर सकते हैं। लेकिन अगर आप नहीं चाहते हैं (या जरूरत है), तो यहां मेरा ले लिया गया है:
जैसा कि आप पहले ही जानते हैं, सूची के सभी तत्वों को एक ही प्रकार की आवश्यकता है। विभिन्न प्रकार के तत्वों की सूची रखना बहुत उपयोगी नहीं है, क्योंकि तब आप अपनी प्रकार की जानकारी को फेंक देते हैं।
हालांकि, इस मामले में, जब आप दूर प्रकार की जानकारी फेंकना चाहते हैं (आप केवल मूल्य के खींचने योग्य भाग में रूचि रखते हैं), तो आप अपने मूल्यों को उस प्रकार के रूप में बदलने का सुझाव देंगे जो केवल खींचने योग्य है।
type Drawable = IO()
shapes :: [Drawable]
shapes = [draw (Circle 5 10), draw (Circle 20 30), draw (Rectangle 10 15)]
मुमकिन है, अपने वास्तविक कुछ Drawable
हो जाएगा बस IO()
से अधिक दिलचस्प (शायद कुछ की तरह: MaxWidth -> IO()
)।
और आलसी मूल्यांकन के कारण, वास्तविक मूल्य तब तक नहीं खींचा जाएगा जब तक आप sequence_
जैसी किसी चीज़ के साथ सूची को मजबूर नहीं करते। तो आपको साइड इफेक्ट्स के बारे में चिंता करने की ज़रूरत नहीं है (लेकिन आप शायद पहले से ही shapes
के प्रकार से देख चुके हैं)।
बस पूरा हो (और यह जवाब में मेरी टिप्पणी को शामिल) के लिए: यह एक अधिक सामान्य कार्यान्वयन है उपयोगी अगर Shape
अधिक कार्य करता है:
type MaxWith = Int
class Shape a where
draw :: a -> MaxWidth -> IO()
size :: a -> Int
type ShapeResult = (MaxWidth -> IO(), Int)
shape :: (Shape a) => a -> ShapeResult
shape x = (draw x, size x)
shapes :: [ShapeResult]
shapes = [shape (Circle 5 10), shape (Circle 20 30), shape (Rectangle 10 15)]
यहाँ, shape
समारोह बदल देती है एक Shape a
Shape
कक्षा में सभी कार्यों को बस कॉल करके ShapeResult
मान में मूल्य।आलस्य के कारण, जब तक आपको उनकी आवश्यकता न हो, तब तक किसी भी मूल्य का वास्तव में गणना नहीं की जाती है।
ईमानदार होने के लिए, मुझे नहीं लगता कि मैं वास्तव में इस तरह के निर्माण का उपयोग करूंगा। मैं या तो ऊपर से Drawable
-विधि का उपयोग करता हूं, या यदि अधिक सामान्य समाधान की आवश्यकता है, तो GADT का उपयोग करें। कहा जा रहा है, यह एक मजेदार व्यायाम है।
मुझे संकलन करने के लिए आपका उदाहरण नहीं मिल सका। लेकिन, आपके द्वारा संदर्भित विकी पेज पूरी तरह से मेरे प्रश्न का उत्तर देता है। –
अभी आज़माएं - मेरे पास 'आकार' था जहां मुझे 'आकार' के लिए डेटा कन्स्ट्रक्टर के हस्ताक्षर में 'IsShape' होना चाहिए था। –
भविष्य के पाठकों के लिए यह ध्यान देने योग्य है कि इस दृष्टिकोण का नुकसान यह है कि 'आकार' कंटेनर से मंडल और आयतों को प्राप्त करने वाला कोड 'IsShape' उदाहरण में दिए गए किसी भी * अन्य गुणों का उपयोग करने में सक्षम नहीं होगा; आप निर्देशांक पर नहीं पहुंच सकते हैं, यह नहीं बता सकते कि यह 'सर्किल' या 'आयत' है, और किसी भी अन्य कार्यों को कॉल नहीं कर सकता जो विशेष रूप से किसी भी आकार के बजाय मंडलियों या आयतों पर काम करता है। यह खुलेपन का मौलिक परिणाम है गणेश के बारे में बात कर रहा है (और जब आप "डाउनकास्ट" करने के लिए मजबूर महसूस करते हैं तो स्थिर रूप से टाइप किए गए ओओ प्रोग्रामिंग में दिखाया जाता है)। – Ben