2011-11-12 17 views
50

मेरे पास एक स्कीमा है जिसमें 6 विभिन्न प्रकार की इकाइयां हैं, लेकिन उनमें से सभी में बहुत सी चीजें आम हैं। मैंने सोचा कि मैं शायद इस स्तर पर इस सामान्यता को बहुत कम कर सकता हूं, लेकिन मैंने हास्केल डीबी और अतिव्यापी उदाहरणों के साथ एक समस्या को मारा है। यहाँ कोड मैं के साथ शुरू किया है, जो ठीक काम करता है:मैं पॉलिमॉर्फिक फ़ील्ड के साथ हास्केलडीबी का उपयोग कैसे कर सकता हूं? (ओवरलैपिंग उदाहरणों में समस्याएं)

import Database.HaskellDB 
import Database.HaskellDB.DBLayout 

data Revision a = Revision deriving Eq 
data Book = Book 

instance FieldTag (Revision a) where 
    fieldName _ = "rev_id" 

revIdField :: Attr (Revision Book) (Revision Book) 
revIdField = mkAttr undefined 

branch :: Table (RecCons (Revision Book) (Expr (Revision Book)) RecNil) 
branch = baseTable "branch" $ hdbMakeEntry undefined 
bookRevision :: Table (RecCons (Revision Book) (Expr (Revision Book)) RecNil) 
bookRevision = baseTable "book_revision" $ hdbMakeEntry undefined 

masterHead :: Query (Rel (RecCons (Revision Book) (Expr (Revision Book)) RecNil)) 
masterHead = do 
    revisions <- table bookRevision 
    branches <- table branch 
    restrict $ revisions ! revIdField .==. branches ! revIdField 
    return revisions 

यह ठीक काम करता है, लेकिन branch भी विशिष्ट है।

branch :: Table (RecCons (Revision entity) (Expr (Revision entity)) RecNil) 
branch = baseTable "branch" $ hdbMakeEntry undefined 

हालांकि, इस परिवर्तन के साथ, मैं निम्नलिखित त्रुटि मिलती है:: क्या मैं वास्तव में व्यक्त करना चाहता हूँ निम्नलिखित है

Overlapping instances for HasField 
          (Revision Book) 
          (RecCons (Revision entity0) (Expr (Revision entity0)) RecNil) 
    arising from a use of `!' 
Matching instances: 
    instance [overlap ok] HasField f r => HasField f (RecCons g a r) 
    -- Defined in Database.HaskellDB.HDBRec 
    instance [overlap ok] HasField f (RecCons f a r) 
    -- Defined in Database.HaskellDB.HDBRec 
(The choice depends on the instantiation of `entity0' 
To pick the first instance above, use -XIncoherentInstances 
when compiling the other instance declarations) 
In the second argument of `(.==.)', namely `branches ! revIdField' 
In the second argument of `($)', namely 
    `revisions ! revIdField .==. branches ! revIdField' 
In a stmt of a 'do' expression: 
     restrict $ revisions ! revIdField .==. branches ! revIdField 

मैं आँख बंद करके -XOverlappingInstances और -XIncoherentInstances इस पर फेंक की कोशिश की है, लेकिन वह मदद नहीं करता है (और मैं वास्तव में समझना चाहता हूं कि एक प्रकार के चर के साथ एक ठोस प्रकार को बदलने का कारण यह इतना समस्याग्रस्त हो जाता है)।

कोई भी मदद और सलाह की सराहना की जाएगी!

+0

उपयोगकर्ता मार्गदर्शिका के अनुसार http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#undecidable-instances IncoherentInstances को डेटाबेस में जोड़ा जाना होगा। HaskellDB। एचडीबीआरईसी प्रभावी होने के लिए। –

+0

विशेष रूप से: इच्छा ओवरलैप हो या बेतुका उदाहरण घोषणा ही है, उपस्थिति से या अन्यथा -XOverlappingInstances और -XIncoherentInstances झंडे जब कि मॉड्यूल परिभाषित किया जा रहा है नियंत्रित की संपत्ति है। –

उत्तर

2
इस सवाल का उम्र के साथ

, यह शायद आप के लिए कोई फर्क का जवाब की बहुत देर हो चुकी है, लेकिन हो सकता है किसी अन्य व्यक्ति के लिए एक समान समस्या के साथ आता है ...

यह करने के लिए नीचे आता है तथ्य यह है कि अनुमानित नहीं किया जा सकता है किको संदर्भित करने के लिए branchmasterHead में उपयोग किया जाता है। त्रुटि संदेश है कि पढ़ता

The choice depends on the instantiation of `entity0'

का हिस्सा आपको बताता है जहां विशेष रूप से है कि तुम क्या entity0 होना चाहिए के बारे में अधिक जानकारी देने के लिए की जरूरत है अस्पष्टता को दूर करने की जरूरत है,। चीजों की मदद करने के लिए आप कुछ प्रकार की टिप्पणियां दे सकते हैं।

सबसे पहले, के रूप में

type BranchTable entity = Table (RecCons (Revision entity) (Expr (Revision entity)) RecNil) 
branch :: BrancTable entity 
branch = baseTable "branch" $ hdbMakeEntry undefined 

branch को परिभाषित करने और उसके बाद masterHead बदलने को पढ़ने के लिए

masterHead :: Query (Rel (RecCons (Revision Book) (Expr (Revision Book)) RecNil)) 
masterHead = do 
    revisions <- table bookRevision 
    branches <- table (branch :: BranchTable Book) 
    restrict $ revisions ! revIdField .==. branches ! revIdField 
    return revisions 

नोट प्रकार एनोटेशन branch के लिए लागू: branch :: BranchTable Book जो अस्पष्टता है कि प्रकार की त्रुटि पैदा कर रहा था दूर करने के लिए कार्य करता है ।

उस में एक Revision e क्षेत्र के साथ masterHead कुछ भी करने के लिए लागू करने के लिए, तो आप इस परिभाषा का उपयोग कर सकते हैं:

masterHead :: (ShowRecRow r, HasField (Revision e) r) => Table r -> e -> Query (Rel r) 
masterHead revTable et = 
    do revisions <- table revTable 
     branches <- table branch' 
     restrict $ revisions ! revIdField' .==. branches ! revIdField' 
     return revisions 
    where (branch', revIdField') = revBundle revTable et 
     revBundle :: HasField (Revision e) r => Table r -> e -> (BranchTable e, Attr (Revision e) (Revision e)) 
     revBundle table et = (branch, revIdField) 

et तर्क क्या e प्रकार होना चाहिए निर्दिष्ट करने के लिए की जरूरत है और सिर्फ undefined के लिए जिम्मेदार माना जा सकता है

masterHead bookRevision (undefined :: Book) 

जो एसक्यूएल को बनाने वाला के रूप में उचित प्रकार

SELECT rev_id1 as rev_id 
FROM (SELECT rev_id as rev_id2 
     FROM branch as T1) as T1, 
    (SELECT rev_id as rev_id1 
     FROM book_revision as T1) as T2 
WHERE rev_id1 = rev_id2 

हालांकि इसे FlexibleContexts की आवश्यकता होती है, लेकिन इसे पूछताछ के मॉड्यूल पर HaskellDB को पुन: संकलित किए बिना लागू किया जा सकता है।

+0

बहुत देर हो चुकी नहीं है! यह बस कुछ दिलचस्प शौक काम है, इसलिए कोई समय सीमा नहीं है :) हालांकि, यह समस्या को हल करने के लिए प्रतीत नहीं होता है। मैं पुस्तक के संदर्भ में मास्टरहेड को परिभाषित नहीं करना चाहता क्योंकि यह इकाई प्रकार पर बहुलक होना है। ऐसी अन्य संस्थाएं भी हैं जिनमें मास्टरहेड (प्रकाशक, संस्करण) भी हैं। इसका क्रूक्स यह है कि इन इकाइयों के प्रकार मास्टरहेड के साथ पैकेज के बाहर परिभाषित किए जाने का इरादा रखते हैं, क्योंकि मास्टर हेड स्टफ को बुनियादी इन-हाउस फ्रेमवर्क से प्रदान किया जाना है। – ocharles

+0

@ocharles, तो आप विशेष रूप से 'bookRevision' का उपयोग करने के बजाय बेस तालिका का पैरामीटर लेने के लिए 'masterHead' चाहते हैं? –

+0

ठीक है, फिर से देखा - हाँ, मास्टरहेड भी पैरामीट्रिक है क्योंकि उन अन्य प्रकारों में 'मास्टरहेड' का विचार भी है। मुझे लगता है कि मैं जो भी चाहता था वह अतिरिक्त प्रकारों को पार किए बिना ऐसा करना था। यह एक बड़े समीकरण में मास्टरहेड का उपयोग करने का कार्य है जो आखिरकार अपना प्रकार निर्धारित करेगा। – ocharles