2015-12-14 6 views
6

मैं एक गतिशील भाषा के लिए एक टाइप एएसटी बनाना चाहता हूं। वर्तमान में, मैं संग्रहों को संभालने पर फंस गया हूं। मैं List काफी अच्छी तरह से की घटनाओं को निर्माण कर सकते हैं जबकिएक जीएडीटी फॉर्मेटेड एएसटी में हेटरोजेनस संग्रह के प्रकार को कैसे निर्दिष्ट करें?

{-# LANGUAGE GADTs #-} 
{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE KindSignatures #-} 
{-# LANGUAGE ExistentialQuantification #-} 

data Box = forall s. B s 

data BinOp = Add | Sub | Mul | Div 
      deriving (Eq, Show) 

data Flag = Empty | NonEmpty 

data List :: Flag -> * -> * where 
    Nil :: List Empty a 
    Cons :: a -> List f a -> List NonEmpty a 

data Expr ty where 
    EInt :: Integer -> Expr Integer 
    EDouble :: Double -> Expr Double 
-- EList :: List -> Expr List 

:

*Main> :t (Cons (B (EInt 1)) (Cons (B (EDouble 2.0)) Nil)) 
(Cons (B (EInt 1)) (Cons (B (EDouble 2.0)) Nil)) 
    :: List Box 'NonEmpty 

मैं बिल्कुल यकीन है कि EList के लिए Expr में इस प्रकार के सांकेतिक शब्दों में बदलना करने के लिए कैसे नहीं कर रहा हूँ यहाँ एक प्रतिनिधि कोड नमूना है। क्या मैं यहां पर सही रास्ते पर भी हूं?

+2

आपके पास कोई विषम संग्रह नहीं है - प्रकार 'बॉक्स' बेकार है। आप अनुमान लगाते हैं कि आप मूल्य के साथ कुछ भी नहीं कर सकते हैं, मुझे लगता है कि 'seq'' के अलावा मुझे लगता है .. ऐसा लगता है कि यह सवाल हास्केल प्रति से विषम संग्रहों के बारे में नहीं है, लेकिन हास्केल में एक प्रकार का सिस्टम मॉडलिंग करता है जो विषम संग्रह का समर्थन करता है।हालांकि, यदि आपका मतलब "गतिशील" जैसा है "गतिशील रूप से टाइप किया गया", तो यह मेटा-भाषा (हास्केल) में स्थिर रूप से टाइप करने के लिए गतिशील रूप से टाइप की गई भाषा के प्रतिनिधित्व के लिए समझ में नहीं आता है। – user2407038

+0

संभावित डुप्लिकेट [जीएडीटी में किसी भी 'डेटाकिंड' की सूची] (http://stackoverflow.com/questions/28388715/list-of-any-datakind-in-gadt/)। – user3237465

उत्तर

6

इस समस्या से संपर्क करने का एक तरीका रन-टाइम प्रकार के प्रतिनिधियों के साथ मूल्यों को टैग करना है। मैं यहां स्टेफनी वीरिच का प्रसारण कर रहा हूं। चलो एक छोटा सा उदाहरण है। सबसे पहले, कुछ प्रकार के लिए एक प्रतिनिधित्व दें। यह आमतौर पर सिंगलटन निर्माण के साथ किया जाता है।

data Type :: * -> * where 
    Int :: Type Int 
    Char :: Type Char 
    List :: Type x -> Type [x] 

तो Type Int क्योंकि यह प्रकार Int के रन-टाइम प्रतिनिधि के रूप में कार्य करता है, एक मूल्य है, जो मैं भी Int बुलाया गया है शामिल हैं। यदि आप मोनोक्रोम चीजों में भी रंग देख सकते हैं, Int:: के बाईं ओर लाल है, और के बाद Int है।

अब हम अस्तित्व पैकेजिंग, उपयोगिता को संरक्षित कर सकते हैं।

data Cell :: * where 
(:::) :: x -> Type x -> Cell 

एक Cell अपनी तरह का एक रन-टाइम प्रतिनिधि के साथ टैग एक मूल्य है। आप अपने प्रकार के टैग को पढ़कर मूल्य की उपयोगिता को पुनर्प्राप्त कर सकते हैं। दरअसल, जैसा कि प्रकार प्रथम क्रम संरचनाएं हैं, हम उन्हें समान तरीके से समानता के लिए जांच सकते हैं।

data EQ :: k -> k -> * where 
    Refl :: EQ x x 

typeEQ :: Type x -> Type y -> Maybe (EQ x y) 
typeEQ Int Int = Just Refl 
typeEQ Char Char = Just Refl 
typeEQ (List s) (List t) = case typeEQ s t of 
    Just Refl -> Just Refl 
    Nothing -> Nothing 
typeEQ _ _ = Nothing 

प्रकार प्रतिनिधियों पर एक बूलियन समानता किसी काम का नहीं है: हम समानता परीक्षण की जरूरत है सबूत कि प्रतिनिधित्व किया प्रकार एकीकृत किया जा सकता है के निर्माण के लिए। सबूत-उत्पादन परीक्षण के साथ, हम

gimme :: Type x -> Cell -> Maybe x 
gimme t (x ::: s) = case typeEQ s t of 
    Just Refl -> Just x 
    Nothing -> Nothing 

बेशक, प्रकार टैग लिखना एक उपद्रव है। लेकिन कुत्ते को क्यों रखें और खुद को छाल क्यों करें?

class TypeMe x where 
    myType :: Type x 

instance TypeMe Int where 
    myType = Int 

instance TypeMe Char where 
    myType = Char 

instance TypeMe x => TypeMe [x] where 
    myType = List myType 

cell :: TypeMe x => x -> Cell 
cell x = x ::: myType 

और अब हम जैसे

myCells :: [Cell] 
myCells = [cell (length "foo"), cell "foo"] 

कर सकते हैं और फिर

> gimme Int (head myCells) 
Just 3 
बेशक

मिलता है, यह सब अगर हम ऐसा करने के लिए नहीं था इसलिए बहुत tidier होगा सिंगलटन निर्माण और ऐसे प्रकारों पर पैटर्न-मिलान कर सकता है क्योंकि हम रन-टाइम पर बनाए रखना चुन सकते हैं। मुझे आशा है कि हम वहां पहुंच जाएंगे जब पौराणिक pi क्वांटिफायर कम पौराणिक हो जाता है।

+0

बहुत उपयोगी; धन्यवाद! – troutwine

+0

वैसे भी एक कुत्ता है, हम 'gimme :: TypeMe t => सेल -> शायद टी' लिख सकते हैं। – user3237465

+1

@ उपयोगकर्ता3237465 हां। बेशक दोनों स्पष्ट प्रकार टी -> और अंतर्निहित TypeMe t => संस्करण मौजूद हैं। यह मेरे लिए स्पष्ट नहीं है कि इस संबंध में स्पष्ट से स्पष्ट अंतर्निहित है। लेकिन जब हम चाहते हैं कि वेरिएंट चुनते समय हमारे पैरों पर प्रकाश होना निश्चित रूप से अच्छा है। एक स्पष्ट कार्यकर्ता लिखना अक्सर अच्छा होता है, फिर एक निहित आवरण का पर्दाफाश करें। – pigworker

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