11

किसी भी चाल जब enums पर बेतुका विधेय के सबूत के निर्माण बॉयलरप्लेट से छुटकारा पाने के लिए?

data WineStock : Fruit -> Type where 
    CanonicalWine : WineStock Grape 
    CiderIsWineToo : WineStock Apple 

जो Banana, Orange, Lemon और दूसरों के लिए नहीं रखता है चलो कहते हैं कि मैं

data Fruit = Apple | Banana | Grape | Orange | Lemon | {- many others -} 

और उस प्रकार पर एक विधेय करते हैं,।

यह can be said है कि यह WineStock को Fruit पर एक अनुमान के रूप में परिभाषित करता है; WineStock Grapeसच है (क्योंकि हम उस प्रकार के मूल्य/सबूत का निर्माण कर सकते हैं: CanonicalWine) WineStock Apple के रूप में भी है, लेकिन WineStock Bananaझूठी है, क्योंकि उस प्रकार किसी भी मान/सबूत का निवास नहीं है।


फिर, मैं कैसे प्रभावी ढंग से Not (WineStock Banana), Not (WineStock Lemon), आदि का उपयोग के बारे में जा सकते हैं? ऐसा लगता है कि Grape और Apple के अलावा प्रत्येक Fruit निर्माता के लिए, मैं impossible रों का पूरा मदद कर सकते हैं नहीं है, लेकिन WineStock पर एक मामले विभाजन ऊपर कोड करने के लिए, कहीं है,:

instance Uninhabited (WineStock Banana) where 
    uninhabited CanonicalWine impossible 
    uninhabited CiderIsWineToo impossible 

instance Uninhabited (WineStock Lemon) where 
    uninhabited CanonicalWine impossible 
    uninhabited CiderIsWineToo impossible 

instance Uninhabited (WineStock Orange) where 
    uninhabited CanonicalWine impossible 
    uninhabited CiderIsWineToo impossible 

ध्यान दें कि:

  • कोड दोहराव है, जब विधेय परिभाषा बढ़ता
  • एलओसी विस्फोट हो जाएगा, और अधिक कंस्ट्रक्टर्स प्राप्त कर रहा। बस Not (Sweet Lemon) सबूत कल्पना, यह मानते हुए वहाँ Fruit परिभाषा में कई मिठाई विकल्प हैं।

तो, इस तरह से संतोषजनक प्रतीत नहीं होता है, लगभग अव्यवहारिक

वहाँ और अधिक सुरुचिपूर्ण दृष्टिकोण हैं?

+3

पुराने हास्केल मुहावरे में से कई निर्भर रूप से टाइप किए गए सिस्टम में नहीं बदलते हैं। प्रकार के स्तर पर "गैरकानूनी राज्यों को निर्विवाद बनाना" भी है: मुझे नहीं लगता कि आपको उन असंभव प्रकारों को भी बनाने में सक्षम होना चाहिए। मैं शायद इस उदाहरण को (कुछ मोटे तौर पर पसंद करता हूं) के रूप में तैयार करता हूं जो कि एक प्रकार का फल है जो शराब 'डेटा वाइनफ्रूट = अंगूर बना सकता है। ऐप्पल 'और अन्य फलों' डेटा फल = वाइनफ्रूट वाइनफ्रूट | केले | ऑरेंज | Lemon' –

+4

@BenjaminHodgson, कि दृष्टिकोण अलग गिर करने के लिए जब आप 'PieFruit',' SaladFruit', 'WeaponFruit', आदि – dfeuer

+2

जोड़ने के लिए यह देखते हुए कि आप इदरिस में हैं, तुम क्यों' WineStock' के लिए एक डेटाप्रकार परिभाषित कर रहे हैं चाहते हैं शुरू होता है ? तुम सिर्फ परिभाषित कर सकता हूँ नहीं 'isWineStock' एक मूल्य के स्तर समारोह के रूप में और सबूत में उपयोग जहां उपयुक्त हो? – sclv

उत्तर

4

@slcv सही है: एक समारोह है कि गणना करता है एक फल एक संपत्ति को संतुष्ट करता है या बल्कि नहीं विभिन्न आगमनात्मक विधेय के निर्माण की तुलना में आप इस भूमि के ऊपर से छुटकारा पाने के लिए अनुमति देगा कि क्या इस्तेमाल करते हैं।

यहाँ कम से कम सेटअप है:

data Is : (p : a -> Bool) -> a -> Type where 
    Indeed : p x = True -> Is p x 

isnt : {auto eqF : p a = False} -> Is p a -> b 
isnt {eqF} (Indeed eqT) = case trans (sym eqF) eqT of 
          Refl impossible 

Is p x सुनिश्चित करता है कि संपत्ति p तत्व x (ताकि इदरिस संदर्भ में प्रकट नहीं करता मैं एक आगमनात्मक प्रकार के बजाय एक प्रकार उर्फ ​​इस्तेमाल की रखती है एक छेद की है, यह इस तरह से) को पढ़ने के लिए आसान है।

isnt prf जाली प्रमाण prf जब भी typechecker का सबूत है कि स्वचालित रूप से p a = False (Refl के माध्यम से या संदर्भ में एक धारणा है) उत्पन्न करने में सक्षम है खारिज।

बार जब आप इन है, तो आप केवल सकारात्मक मामलों की गणना और एक कैचऑल

wineFruit : Fruit -> Bool 
wineFruit Grape = True 
wineFruit Apple = True 
wineFruit _  = False 

weaponFruit : Fruit -> Bool 
weaponFruit Apple = True 
weaponFruit Orange = True 
weaponFruit Lemon = True 
weaponFruit _  = False 

आप उचित निर्णय समारोह के साथ Is बुला प्रकार उपनाम के रूप में अपने मूल विधेय परिभाषित कर सकते हैं जोड़कर अपने गुण को परिभाषित करने शुरू कर सकते हैं:

:
WineStock : Fruit -> Type 
WineStock = Is wineFruit 

और, यकीन है कि पर्याप्त, isnt आप असंभव मामलों को खारिज करने की अनुमति देता है

dismiss : WineStock Orange -> Void 
dismiss = isnt 
+0

वाह, बढ़िया, धन्यवाद! – ulidtko

संबंधित मुद्दे