2013-01-11 21 views
7

मेरे डेटा प्रकार हमेशा कम से कम दो पैरामीटर होगा, और पिछले दो मापदंडों हमेशा 'क्यू' और 'मी' क्रमशः,:प्रकार डीकंस्ट्रक्शन

{-# LANGUAGE TypeFamilies, FlexibleContexts, UndecidableInstances, TypeOperators, DataKinds, ConstraintKinds, FlexibleInstances #-} 

data D1 q m = D1 q 
data D2 t q m = D2 q 

class Foo a where -- a has kind * -> * 
    f :: a x -> a x 

class (Foo b) => Bar b where -- b has kind * -> * 
    -- the purpose of g is to change ONE type parameter, while fixing the rest 
    -- the intent of the equality constraints is to decompose the parameter b into 
    -- its base type and 'q' parameter, then use the same base type with a *different* 
    -- `q` parameter for the answer 
    g :: (b ~ bBase q1, b' ~ bBase q2) => b m -> b' m 

instance (Foo (D2 t q), Integral q) => Bar (D2 t q) where 
    g (D2 q) = D2 $ fromIntegral q -- LINE 1 

त्रुटि

Could not deduce (bBase ~ D2 t0) (LINE 1) 
में इस कार्यक्रम के परिणाम

जब मैंने उदाहरण लिखा, तो मुझे निश्चित रूप से bBase ~ D2 t का इरादा था। मुझे लगता है कि टी किसी भी तरह से बाध्य नहीं है (इसलिए टी 0 की शुरूआत), और मुझे नहीं पता कि जीएचसी इस प्रकार को किस तरह से रद्द कर सकता है या नहीं। या शायद मैं कुछ मूर्खतापूर्ण कर रहा हूँ।

इस बिंदु पर अधिक, यदि मैं बार में पैरामीटर बना देता हूं तो इस प्रकार की समानता/प्रकार deconstruction आवश्यक नहीं होगा * -> * -> *। लेकिन तब मैं फू बाधा को लागू नहीं किया जा सका:

class (Foo (b q)) => Bar b where -- b has kind * -> * -> * 
    g :: b q m -> q b' -- this signature is now quite simple, and I would have no problem implementing it 

इसका कारण यह है क्ष बार के लिए एक पैरामीटर नहीं है काम नहीं करेगा, और मैं नहीं चाहता कि यह बार के लिए एक पैरामीटर करना चाहते हैं।

मैं एक समाधान दो अतिरिक्त "डमी" का उपयोग कर जुड़े प्रकार पाया है, लेकिन मैं वास्तव में उनके आसपास होने अगर मैं उन्हें जरूरत नहीं है पसंद नहीं:

class (Foo b, b ~ (BBase b) (BMod b)) => Bar b where -- b has kind * -> * 
    type BBase b :: * -> * -> * 
    type BMod b :: * 

    g :: (Qux (BMod b), Qux q') => b m -> (BBase b) q' m 

instance (Foo (D2 t q), Integral q) => Bar (D2 t q) where 
    type BBase (D2 t q) = D2 t 
    type BMod (D2 t q) = q 

    g (D2 q) = D2 $ fromIntegral q 

यह काम करता है, लेकिन यह स्पष्ट रूप से के बराबर है इस प्रकार का विघटन करना, जो मुझे लगता है कि उदाहरण के सरल प्रकार को अनावश्यक होना चाहिए।

मैं या तो दृष्टिकोण के लिए एक समाधान की तलाश में हूं: या तो मुझे बताएं कि मैं "अधिक लागू" प्रकार पर कक्षा की बाधा को कैसे लागू कर सकता हूं, या मुझे बताएं कि जीएचसी deconstruct प्रकार कैसे बनाना है।

धन्यवाद!

+1

पूर्ण त्रुटि संदेश मैं मिलता है 'amy16.hs: 7: 1: अवैध संतुलन संबंधी बाधा ख ~ bBase q1 (प्रयोग -XGADTs या -XTypeFamilies इस अनुमति के लिए) जब वर्ग विधि की जाँच: जी :: forall (bBase :: * -> * -> *) Q1 (ख ':: * -> *) q2 मीटर। (बी ~ बीबीज़ क्यू 1, बी '~ बीबीएएस क्यू 2) => बीएम -> बी' एम 'बार' के लिए कक्षा घोषणा में विफल, मॉड्यूल लोड किए गए: कोई नहीं। 'इसलिए मुझे लगता है कि आपको या तो' GADTs' भाषा pragma या 'TypeFamilies' pragma, और संभवतः कुछ अन्य pragmas रूप में अच्छी तरह। – mhwombat

+1

मैं उपरोक्त कोड में संकलन झंडे/भाषा pragmas शामिल नहीं किया, लेकिन निश्चित रूप से मैं सब कुछ का उपयोग कर रहा की मैं उन शब्दों में की जरूरत है (जो काम के टुकड़े के सभी बनाना चाहिए): TypeFamilies, FlexibleContexts, UndecidableInstances, TypeOperators, DataKinds , ConstraintKinds, FlexibleInstances – crockeea

उत्तर

1

आप जो वर्णन करते हैं, उससे आपके पास b' :: * -> * -> * है जिसके लिए आप लागू b' t :: * -> * (सभी t के लिए) को बाधित करना चाहते हैं।

आप summise के रूप में, आप या तो एक प्रकार है, जो आपके प्रयास यहाँ है एक b :: * -> * से शुरू deconstruct करने के लिए जरूरत है एक प्रकार आवेदन b = b' t, या एक "अधिक से लागू" पर एक बाधा को लागू करने का परिणाम माना b' :: * -> * -> * के प्रारंभ बिंदु से टाइप करें।

एक प्रकार Deconstructing के बाद से संकलक अगर b यहाँ तक कि "deconstructable" है पता नहीं है, संभव नहीं है। दरअसल, ऐसा नहीं हो सकता है, उदाहरण के लिए, मैं एक उदाहरण instance Bar Maybe कर सकता हूं, लेकिन Maybe को किसी प्रकार b' :: * -> * -> * और कुछ प्रकार t :: * में डिज़ाइन नहीं किया जा सकता है।

class Bar (b :: * -> * -> *) where 
     g :: (Foo (b q1), Foo (b q2)) => b q1 m -> b q2 m 

अपने उदाहरण के लिए एक और शिकन नहीं है:

एक प्रकार b' :: * -> * -> * से बजाय शुरू, b' के एक आवेदन पर की कमी वर्ग के शरीर है, जहां चर मात्रा निर्धारित कर रहे हैं में ले जाया जा सकता है: q1 और q2 में अपनी बाधाएं हो सकती हैं, उदा। D2 उदाहरण के लिए आपको Integral बाधा की आवश्यकता है। हालांकि, Bar सभी मामलों (इस मामले में खाली बाधा) के लिए q1 और q2 पर बाधाओं को हल करता है।अपने D2 उदाहरण तो फिर तुम लिख सकते हैं

class Bar (b :: * -> * -> *) where 
     type Constr b t :: Constraint 
     g :: (Foo (b q1), Foo (b q2), Constr b q1, Constr b q2) => b q1 m -> b q2 m 

(शामिल {-# LANGUAGE ConstraintKinds #-} और GHC.Prim आयात)

:

एक समाधान "बाधा-kinded प्रकार परिवारों" जो उदाहरणों के लिए अपने स्वयं की कमी निर्दिष्ट करने देते हैं उपयोग करने के लिए है
instance Bar (D2 t) where 
     type Constr (D2 t) q = Integral q 
     g (D2 q) = D2 $ fromIntegral q