SORU
12 Kasım 2011, CUMARTESİ


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
9 Temmuz 2012, PAZARTESİ


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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • FOSDEM

    FOSDEM

    13 Ocak 2009
  • Jonathan Flavell

    Jonathan Fla

    1 HAZİRAN 2006
  • MobileTechReview

    MobileTechRe

    6 HAZİRAN 2008