हास्केल में इम्प्लांटेड, स्टैटिक टाइप कास्ट (जबरदस्ती)


9

मुसीबत

हास्केल में निम्नलिखित डिजाइन समस्या पर विचार करें। मेरे पास एक सरल, प्रतीकात्मक ईडीएसएल है जिसमें मैं चर और सामान्य अभिव्यक्ति (बहुभिन्नरूपी बहुपद) जैसे कि व्यक्त करना चाहता हूं x^2 * y + 2*z + 1। इसके अलावा, मैं अभिव्यक्तियों पर कुछ प्रतीकात्मक समीकरणों को कहना चाहता हूं x^2 + 1 = 1, साथ ही परिभाषाओं को भी पसंद करता हूं x := 2*y - 2

लक्ष्य यह है:

  1. चर और सामान्य अभिव्यक्ति के लिए एक अलग प्रकार है - कुछ कार्यों को चर पर लागू किया जा सकता है और जटिल अभिव्यक्ति नहीं। उदाहरण के लिए, एक परिभाषा ऑपरेटर :=प्रकार का हो सकता है (:=) :: Variable -> Expression -> Definitionऔर इसके बाईं ओर के पैरामीटर के रूप में एक जटिल अभिव्यक्ति को पारित करना संभव नहीं होना चाहिए (हालांकि स्पष्ट कास्टिंग के बिना इसके दाहिने हाथ के पैरामीटर के रूप में एक चर को पारित करना संभव होना चाहिए ) ।
  2. अभिव्यक्ति का एक उदाहरण है Num, ताकि पूर्णांक शाब्दिक अभिव्यक्ति को बढ़ावा देने और कुछ सहायक आवरण ऑपरेटरों को शुरू किए बिना जोड़ या गुणा जैसे सामान्य बीजीय संचालन के लिए एक सुविधाजनक अंकन का उपयोग करना संभव हो।

दूसरे शब्दों में, मैं अभिव्यक्ति के लिए एक अंतर्निहित और स्थिर प्रकार कास्ट (जबरदस्ती) रखना चाहूंगा । अब, मुझे पता है कि जैसे कि, हास्केल में कोई निहित प्रकार की जातियां नहीं हैं। फिर भी, कुछ ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग अवधारणाओं (सरल विरासत, इस मामले में) कर रहे हैं व्यक्त , हास्केल के प्रकार प्रणाली में या तो साथ या भाषा एक्सटेंशन के बिना। एक हल्के वाक्यविन्यास को रखते हुए मैं उपरोक्त दोनों बिंदुओं को कैसे संतुष्ट कर सकता हूं? क्या यह भी संभव है?

विचार-विमर्श

यह स्पष्ट है कि यहाँ मुख्य समस्या है Numप्रतिबंध, जैसे

(+) :: Num a => a -> a -> a

सिद्धांत रूप में, एक एकल (सामान्यीकृत) बीजीय डेटा प्रकार को चर और भाव दोनों के लिए लिखना संभव है। फिर, कोई :=इस तरह से लिख सकता है , कि बाएं हाथ की अभिव्यक्ति में भेदभाव किया जाता है और केवल एक रनवे निर्माता को स्वीकार किया जाता है, एक रन-टाइम त्रुटि के साथ अन्यथा। हालांकि यह एक साफ, स्थिर (संकलन-समय) समाधान नहीं है ...

उदाहरण

आदर्श रूप से, मैं एक हल्के वाक्यविन्यास को प्राप्त करना चाहूंगा जैसे कि

computation = do
  x <- variable
  t <- variable

  t |:=| x^2 - 1
  solve (t |==| 0)

विशेष रूप से, मैं इस तरह t + 1 |:=| x^2 - 1से संकेतन की :=परिभाषा देना चाहता हूं क्योंकि एक चर की परिभाषा देनी चाहिए न कि पूरे बाएं हाथ की अभिव्यक्ति।


1
हो सकता है आप एक इस्तेमाल कर सकते हैं class FromVar eएक विधि के साथ fromVar :: Variable -> eऔर के लिए उदाहरणों प्रदान Expressionऔर Variable, फिर अपने चर बहुरूपी प्रकार है है x :: FromVar e => eआदि मैं परीक्षण नहीं किया है कितनी अच्छी तरह यह काम करता है के बाद से मैं अपने फोन पर कर रहा हूँ।
मोर ए।

मुझे यकीन नहीं है कि FromVarटाइपकास्ट कैसे मदद का होगा। मैं Exprएक उदाहरण रखते हुए स्पष्ट जातियों से बचना चाहता हूं Num। मैंने एक संकेतन का उदाहरण जोड़ते हुए प्रश्न को संपादित किया जिसे मैं प्राप्त करना चाहूंगा।
मैकीज बेंदकोव्स्की

जवाबों:


8

घटाव के बजाय बहुरूपता का लाभ उठाने के लिए (क्योंकि हास्केल में आपके पास सब कुछ है), "एक चर एक अभिव्यक्ति है" मत सोचो, लेकिन "चर और अभिव्यक्ति दोनों में कुछ ऑपरेशन समान हैं"। उन कार्यों को एक प्रकार की श्रेणी में रखा जा सकता है:

class HasVar e where fromVar :: Variable -> e

instance HasVar Variable where fromVar = id
instance HasVar Expression where ...

फिर, कास्टिंग के बजाय, चीजों को बहुरूपी बनाएं। यदि आपके पास है v :: forall e. HasVar e => e, तो इसका उपयोग एक अभिव्यक्ति के रूप में और एक चर के रूप में दोनों किया जा सकता है।

example :: (forall e. HasVar e => e) -> Definition
example v = (v := v)  -- v can be used as both Variable and Expression

 where

  (:=) :: Variable -> Expression -> Definition

नीचे दिए गए कोड को टाइप करने के लिए कंकाल: https://gist.github.com/Lysxia/da30abac357deb7981412f1faf0d2103

computation :: Solver ()
computation = do
  V x <- variable
  V t <- variable
  t |:=| x^2 - 1
  solve (t |==| 0)

दिलचस्प है, धन्यवाद! मैंने एक संक्षिप्त क्षण के लिए अस्तित्वगत प्रकारों के पीछे दोनों चर और भावों को छिपाने पर विचार किया, हालांकि मैंने इस विचार को खारिज कर दिया क्योंकि इसने अतिरिक्त अंकन पेश किया, आपका देखें V। शुरू में ऐसा नहीं था जो मैं चाहता था, लेकिन शायद मैं इसे खारिज करने के लिए बहुत जल्दी था ... शायद मैं अपारदर्शी से छुटकारा नहीं पा सकता V। संबंधित नोट पर, मैं कैसे का एक उदाहरण बना सकता हूं V (forall e . HasVar e => e)? Coq में, मैं एक प्रेरक प्रकार पर मिलान प्रकार और पैटर्न का उपयोग करूंगा, लेकिन यह स्पष्ट नहीं है कि हास्केल में इसे कैसे प्राप्त किया जाए।
मैकिज बेंदकोव्स्की

1
आप w :: Variableकिसी तरह हड़प सकते हैं और इसके fromVarलिए आवेदन कर सकते हैं variable = (\w -> V (fromVar w)) <$> (_TODO_ :: Solver Variable):।
ली-याओ ज़िया

1
और Vimpredicative प्रकारों से बचा जा सकता है, लेकिन यह अभी भी WIP है। या हम variableपरोक्ष रूप से के बजाय स्पष्ट रूप से एक बहुरूपी तर्क के साथ निरंतरता बना सकते हैं (>>=)
ली-याओ ज़िया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.