GADTs

2016-11-08 18 views
5

के लिए पाने पढ़ें उदाहरण मैं कैसे स्वचालित रूप से इस GADTs के लिए एक Read उदाहरण प्राप्त कर सकते हैं:GADTs

{-# LANGUAGE GADTs, StandaloneDeriving #-} 

data TypeDec a where 
    TypeDecInt :: TypeDec Int 
    TypeDecString :: TypeDec String 

deriving instance Show (TypeDec a) 

data Bar where 
    Bar :: (Show a, Read a) => TypeDec a -> a -> Bar 

deriving instance Show Bar 

विचार है कि Bar एक serializable प्रकार है।

instance Read Bar where 
    readsPrec _ s = 
    let (bar, tup) = second breaks . breaks $ s 
    in if "Bar" == bar then uncurry parse tup else [] 
    where 
     parse :: String -> String -> [(Bar, String)] 
     parse tdec = case tdec of 
     "TypeDecInt" -> parse' TypeDecInt 
     "TypeDecString" -> parse' TypeDecString 
     _    -> const [] 

     parse' :: (Show a, Read a) => TypeDec a -> String -> [(Bar, String)] 
     parse' tdec s = [(Bar tdec (read s), "")] 

     breaks :: String -> (String, String) 
     breaks = second (drop 1) . break (== ' ') 
+2

यह टेम्पलेट हास्केल का उपयोग कर पूरी तरह से करने योग्य है। किसी को सिर्फ @dfeuer द्वारा उल्लिखित दृष्टिकोण का उपयोग करने की आवश्यकता होगी (यानी 'GHC.Read.choose'' के बजाय 'केस' का उपयोग करना)। – Alec

+0

@Alec क्या आप टेम्पलेट हास्केल के साथ 'रीड' उदाहरण प्राप्त करने के लिए कोई उदाहरण/ट्यूटोरियल जानते हैं? – homam

+0

[यह] (https://wiki.haskell.org/Template_haskell/Instance_deriving_example) अच्छा लग रहा है। – Alec

उत्तर

4

मैं नहीं जानता:

मैं निम्नलिखित स्निपेट द्वारा या Parsec द्वारा एक Read उदाहरण लिख सकते हैं, लेकिन यह देखते हुए कि मैं TypeDec और इस विभिन्न मॉड्यूल में Bar लिए इसी तरह के कई प्रकार है एक बॉयलरप्लेट है एक सामान्य समाधान का। जैसा कि कहा गया है, यह readPrec विधि को परिभाषित करते हुए Read उदाहरणों लिखने के लिए एक बहुत आसान है (देखें Text.Read विशेष रूप से, कुछ अतिरिक्त कार्यों के लिए Text.ParserCombinators.ReadPrec, और शायद Text.ParserCombinators.ReadP और भी अधिक के लिए) के बजाय Parsec का उपयोग कर या readsPrec को परिभाषित करने की। यह पूर्ण तेज़ नहीं है जिसे आप लिख सकते हैं, लेकिन यह उचित रूप से तेज़ होना चाहिए।

import Text.Read 

instance Read Bar where 
    readListPrec = readListPrecDefault 

    readPrec = parens $ do 
    Ident "Bar" <- lexP 
    Ident td <- parens lexP 
    case td of 
     "TypeDecInt" -> Bar TypeDecInt <$> readPrec 
     "TypeDecString" -> Bar TypeDecString <$> readPrec 
     _ -> empty 

तो TypeDec अधिक जटिल है, और आप TypeDec Int और TypeDec String (FlexibleInstances या एक सहायक वर्ग का प्रयोग करके) के लिए Read मामले हैं तो फिर आप की संभावना कुछ अधिक मॉड्यूलर चाहता हूँ:

instance Read Bar where 
    readListPrec = readListPrecDefault 
    readPrec = parens $ do 
    Ident "Bar" <- lexP 
    (Bar <$> readPrec <*> (readPrec :: ReadPrec Int)) 
     <|> (Bar <$> readPrec <*> (readPrec :: ReadPrec String)) 

ध्यान दें कि दूसरे उदाहरण में, जीएचसी अपने आप से यह नहीं समझ सकता कि विकल्पों के किस प्रकार के पास होना चाहिए, लेकिन जब हम दूसरे क्षेत्र के प्रकार को ठीक करते हैं, तो अनुमान पहले क्षेत्र में फैलता है। तो पहले विकल्प में, हम केवल "TypeDecInt" देखेंगे और दूसरे में हम केवल "TypeDecString" देखेंगे।


dependent-sum पैकेज एक प्रकार है कि अपने Bar सामान्यीकरण करता परिभाषित करता है।

data DSum tag f = forall a . !(tag a) :=> f a 

यह भी कुछ अतिरिक्त कक्षाओं का उपयोग कर DSum के लिए एक Read उदाहरण परिभाषित करता है। सामान्य दृष्टिकोण ठोस दिखता है, लेकिन मैं दो परिवर्तनों की सिफारिश करता हूं। सबसे पहले सूचियों के साथ झगड़ा करने के बजाय ReadPrec का उपयोग करना है। दूसरी निम्नलिखित (बहुत सरल) अस्तित्व एक साथ उच्च रैंक GReadResult प्रकार बदलने के लिए है:

data GReadResult t = forall a . GReadResult (t a) 
बेशक

, इन परिवर्तनों को यह अपने आप को लागू करने के लिए आप के लिए बाध्य करेगा, लेकिन यह ठीक है।

+0

'निर्भर-योग' एक दिलचस्प lib है। लेकिन इसके [उदाहरण] (https://github.com/mokus0/dependent-sum/blob/master/examples/FooGADT.hs#L72) से ऐसा लगता है कि मुझे अभी भी 'ग्रिड' उदाहरण परिभाषित करना है (और कुछ बॉयलरप्लेट लिखें 'टैग' प्रकार के प्रत्येक कन्स्ट्रक्टर के लिए)। – homam

+0

@ होमाम, हां, 'डीएसयूएम' दृष्टिकोण सिर्फ उदाहरणों पर एक निश्चित संरचना लगाता है; यदि आप संबंधित उपकरणों का उपयोग नहीं करना चाहते हैं तो यह आपको कुछ जीतने वाला नहीं है। मुझे लगा कि यह उल्लेखनीय होगा। – dfeuer

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

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