2012-08-22 21 views
14

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

यहाँ मेरी दु: ख की व्याख्या करने के एक उदाहरण है:

data Nat = Z | S Nat deriving Eq 

data Le :: Nat -> Nat -> * where 
    Le_base :: Le a a 
    Le_S :: Le a b -> Le a (S b) 

class ReformOp n m where 
    reform :: Le (S n) (S m) -> Le n m 

instance ReformOp a a where 
    reform Le_base = Le_base 

instance ReformOp a b => ReformOp a (S b) where 
    reform (Le_S p) = Le_S $ reform p 

class TransThm a b c where 
    trans :: Le a b -> Le b c -> Le a c 

instance TransThm a a a where 
    trans = const 

instance TransThm a a b => TransThm a a (S b) where 
    trans Le_base (Le_S p) = Le_S $ trans Le_base p 

instance (TransThm a b c, ReformOp b c) => TransThm a (S b) (S c) where 
    trans (Le_S p) q = Le_S $ trans p $ reform q 

हम 2 प्रकार वर्गों (प्रमेय के लिए एक, एक उपयोगिता आपरेशन के लिए एक) और 5 इंस्टेंस - बस एक छोटी सी प्रमेय के लिए। आदर्श रूप में, हास्केल इस समारोह में दिखाई दे सकता है:

-- not working, I understand why 
trans :: Le a b -> Le b c -> Le a c 
trans Le_base Le_base = Le_base 
trans Le_base (Le_S p) = Le_S $ trans Le_base p 
trans (Le_S p) q = Le_S $ trans p $ reform q 

और अपने दम पर प्रत्येक खंड प्रकार की अच्छी तरह जांच, और तय जो मामलों संभव (इस प्रकार से मिलान करने के कोशिश कर रहा लायक) कर रहे हैं प्रति-कॉल और जो ऐसा है, तो नहीं कर रहे हैं जब बुला trans Le_base Le_base हास्केल नोटिस करेगा कि केवल पहला मामला तीन चर के समान होने की अनुमति देता है, और केवल पहले खंड पर मिलान करने का प्रयास करता है।

उत्तर

13

मुझे नहीं लगता कि trans की आपकी पैटर्न-मिलान परिभाषा Agda या Coq में कैसे काम करेगी।

आप के बजाय निम्नलिखित लिखते हैं, यह काम करता है:

reform :: Le (S n) (S m) -> Le n m 
reform Le_base   = Le_base 
reform (Le_S Le_base) = Le_S Le_base 
reform (Le_S (Le_S p)) = Le_S (reform (Le_S p)) 

trans :: Le a b -> Le b c -> Le a c 
trans Le_base q  = q 
trans (Le_S p) Le_base = Le_S p 
trans (Le_S p) (Le_S q) = Le_S (trans p (reform (Le_S q))) 

बेशक, आप भी अधिक सीधे निर्धारित कर सकते हैं:

trans :: Le a b -> Le b c -> Le a c 
trans p Le_base = p 
trans p (Le_S q) = Le_S (trans p q) 
+0

दरअसल, आप सही कर रहे हैं! –

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