संभवतः एक अस्तित्व संभवतः आप यहां नहीं चाहते हैं; या w
पर Dangerous a
मान में वास्तविक प्रकारों को "निरीक्षण" करने का कोई तरीका नहीं है, इसलिए आप Error
और Show
द्वारा दिए गए संचालन तक पूरी तरह से सीमित हैं।
दूसरे शब्दों में, केवल एक चीज के बारे में क्या आप जानते हैं w
है कि आप इसे एक String
में बदल सकते हैं, तो यह रूप में अच्छी तरह सिर्फ एक String
(अनदेखी चीजों को आसान बनाने के पूर्वता), और केवल एक चीज के बारे में आप e
जानते हो सकता है यह है कि आप इसे String
में बदल सकते हैं, आप इसमें String
एस बदल सकते हैं, और आपके पास इसका विशिष्ट मान है (noMsg
)। जोर देने या जांचने का कोई तरीका नहीं है कि ये प्रकार किसी अन्य के समान हैं, इसलिए एक बार जब आप उन्हें Dangerous
में डाल देते हैं, तो उन प्रकारों की किसी भी विशेष संरचना को पुनर्प्राप्त करने का कोई तरीका नहीं है।
क्या त्रुटि संदेश कह रहा है यह है कि अनिवार्य रूप से, runDangerous
दावों के लिए अपने प्रकार है कि आप के लिए एक (Either e a, [w])
में एक Dangerous
बदल सकते हैं किसी भीe
और w
प्रासंगिक उदाहरणों को है। यह स्पष्ट रूप से सत्य नहीं है: आप केवल को उस प्रकार में एकe
और w
के विकल्प में बदल सकते हैं: जिसे वह बनाया गया था। w1
सिर्फ इसलिए है क्योंकि आपके Dangerous
प्रकार को एक प्रकार परिवर्तनीय w
के साथ परिभाषित किया गया है, और इसलिए runDangerous
है, इसलिए जीएचसी नाम संघर्ष से बचने के लिए उनमें से एक का नाम बदलता है।
प्रकार आप runDangerous
देने की आवश्यकता इस तरह दिखता है:
runDangerous
:: (forall e w. (Error e, Show e, Show w) => (Either e a, [w]) -> r)
-> Dangerous a -> r
जो एक समारोह जो इतने लंबे समय पहले की तरह e
की किसी भी विकल्प और w
के लिए प्रकार (Either e a, [w])
के एक मूल्य स्वीकार करेंगे दिया दिए गए उदाहरण, और Dangerous a
, उस कार्य के परिणाम का उत्पादन करता है। अपने सिर को चारों ओर लेना मुश्किल है!
कार्यान्वयन है के रूप में सरल
runDangerous f (Dangerous m) = f $ runState (runErrorT m) []
जो अपने संस्करण के लिए एक छोटी सी परिवर्तन है। यदि यह आपके लिए काम करता है, तो बढ़िया; लेकिन मुझे संदेह है कि जो कुछ भी आप करने की कोशिश कर रहे हैं उसे हासिल करने का एक सही तरीका है।
ध्यान दें कि runDangerous
के प्रकार को व्यक्त करने के लिए आपको {-# LANGUAGE RankNTypes #-}
की आवश्यकता होगी। फिर, आप अपने परिणाम प्रकार के लिए एक और अस्तित्व को परिभाषित कर सकते हैं:
data DangerousResult a = forall e w. (Error e, Show e, Show w) =>
DangerousResult (Either e a, [w])
runDangerous :: Dangerous a -> DangerousResult a
runDangerous (Dangerous m) = DangerousResult $ runState (runErrorT m) []
और case
साथ परिणाम निकालने, लेकिन आप सावधान रहना होगा, या GHC शिकायत आप e
या w
बच जाने की है कि शुरू कर देंगे - जो runDangerous
के दूसरे रूप में अपर्याप्त रूप से पॉलिमॉर्फिक फ़ंक्शन को पारित करने का प्रयास करने के बराबर है; यानी e
और w
पर runDangerous
गारंटी के प्रकार से अधिक बाधाओं की आवश्यकता होती है।
क्या ऐसा करने के लिए कोई बेहतर (या अधिक मूर्खतापूर्ण) तरीका है? मैं वास्तव में सिर्फ एक त्रुटि मोनड चाहता हूं जो कुछ चेतावनियों के साथ आता है। – So8res
क्यों न केवल 'खतरनाक ई डब्ल्यू ए' के रूप में परिभाषित करें? यहां अस्तित्व की कोई आवश्यकता नहीं है, अगर मैं समझता हूं कि आप क्या हासिल करने की कोशिश कर रहे हैं (जो मुझे शायद नहीं हो सकता है)। – ehird
मेरे पास कुछ मॉड्यूल हैं जो सभी अपनी त्रुटियों और चेतावनियों को फेंक देते हैं, और वे शीर्ष स्तर पर संभाले जाते हैं। शीर्ष स्तर को केवल उन्हें मुद्रित करने की आवश्यकता है, लेकिन विकल्प मॉड्यूल में 'खतरनाक ऑप्टरर ऑप्टवार्निंग [विकल्प]' और टेम्पलेट फ़ाइल में 'खतरनाक टेम्पलेट एरर टेम्पलेट चेतावनी टेम्पलेट' कहने के लिए परेशान करना है, जब वे सभी 'दिखाएंगे'। मैं बहुत सारे बॉयलरप्लेट को हटाने और थोड़ा सा सीखने की कोशिश कर रहा हूं, यह निश्चित रूप से आवश्यक नहीं है। – So8res