Nasıl polimorfik alanlar ile HaskellDB kullanabilir miyim? (Üst üste örnekleri ile ilgili sorunlar)
Varlıkların 6 farklı türleri olan bir şema var, ama hepsinin ortak bir çok şey var. Muhtemelen yazın düzeyde bu ortak bir çok soyut olabilir diye düşündüm, ama HaskellDB ve örtüşen örnekleri ile ilgili bir sorun buldum. Burada çalışan ile başladım kod, ince:
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
Bu iyi çalışır, ama branch
çok özeldir. Aslında ifade etmek istediğim şudur:
branch :: Table (RecCons (Revision entity) (Expr (Revision entity)) RecNil)
branch = baseTable "branch" $ hdbMakeEntry undefined
Ancak, bu değişiklik, aşağıdaki hatayı alıyorum:
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
Denedim körü körüne atma -XOverlappingInstances
-XIncoherentInstances
Bu, ama bunun bir yararı yok (istiyorum aslında neden anlamak yerine bir beton tipi ile a tipi değişken neden bu kadar sorunlu).
Yardım ve tavsiye çok takdir olurdu!
CEVAP
Bu sorunun yaş ile, Eğer başka biri benzer bir sorun varsa muhtemelen sizin için herhangi bir fark yaratmak için bir cevap çok geç ama... belki
entity
branch
masterHead
kullanıldığında Book
başvurmak istediğiniz anlaşılmaktadır olamayacağı ortaya çıkıyor. Okur hata iletisini parçası
Seçim örnekleme bağlıdır `entity0'
entity0
ne olması gerektiği hakkında daha fazla bilgi vermen gerekiyor bu belirsizlik kaldırmak için ihtiyacınız olduğu yerde, özellikle söyler. Bazı tür şeyler yardımcı olmak için notlar verebilirsiniz.
İlk olarak, branch
olarak tanımlayın
type BranchTable entity = Table (RecCons (Revision entity) (Expr (Revision entity)) RecNil)
branch :: BrancTable entity
branch = baseTable "branch" $ hdbMakeEntry undefined
ve daha sonra masterHead
okumak için değiştirin
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
Not türünü branch
uygulanan ek açıklama: tür hataya neden belirsizlik kaldırmak için hizmet veren branch :: BranchTable Book
.
masterHead
Revision e
alanı ile ilgili bir şey yapmak için, bu tanımı kullanabilirsiniz:
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
bağımsız e
türü ne olması gerektiğini belirtmek için gerekli değildir ve sadece doğru tip undefined
bağlanabilir
masterHead bookRevision (undefined :: Book)
SQL üretir
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
bu 33* *gerçi gerektirir, ama HaskellDB derlenmesine olmadan asker modülü için uygulanabilir.
Nasıl bir Android projesinde dış Kavan...
Nasıl Android Geliştirme için MS Visua...
Nasıl Python sistem hostname almak içi...
Bir yığın izleme, nedir ve nasıl uygul...
Nasıl benim iPhone App NSError kullana...