2016-03-02 34 views
9

yılında belirsizliği çözmek için nasıl bir SQL EDSL modellemek için kullanıyorum iki GADTs var. İstemciyi temiz ve basit bir şekilde karşı karşıya bırakmak için Column Selection'a dize değişmezlerini yayınlamak için OverloadedStrings kullanmak istiyorum. benim GADTs

nedenle sadece sorun seçme hem Column Selection s için izin verir ve Reduction s toplamaları gerçekleştirmek sorguları için izin vermek olduğunu

select ["a", "b"] $ from tbl 

yerine

select [Column "a", Column "b"] $ from tbl 

ait yazabilirsiniz.

mean :: Column Selection -> Column Reduction 

select :: [Column a] -> Query b -> Query Selection 
select [mean "a"] $ from tbl 

ve böylece dizeleri [Column a] bu bağlamda belirsizdir. mean değişmez dize bir sütun Seçim olduğunu anlaması için gerekli bağlam sağlar beri Ama select [mean "a"] $ from tbl geçerlidir.

kimse bu karmaşadan çıkış yolu tavsiye edebilir misiniz? Aşağıda

Bulunduğum kodu (ilgisiz örnekler atlanmış)

{-# LANGUAGE 
    GADTs 
    , RankNTypes 
    , DataKinds 
    , TypeFamilies 
    , FlexibleContexts 
    , FlexibleInstances 
    , OverloadedStrings #-} 

data Sz = Selection | Reduction deriving Show 
data Schema = Schema{name :: Maybe String, spec :: [Column Selection]} 

type family ColOp (a :: Sz) (b :: Sz) where 
    ColOp Selection Selection = Selection 
    ColOp Selection Reduction = Selection 
    ColOp Reduction Selection = Selection 
    ColOp Reduction Reduction = Reduction 

data Column (a :: Sz) where 
    Column :: String -> Column Selection 
    Assign :: String -> Column a -> Column a 
    FKey :: String -> Schema -> Column Selection 
    BinExpr :: BinOp -> Column a -> Column b -> Column (ColOp a b) 
    LogExpr :: LogOp -> Column a -> Column b -> Column Selection 
    AggExpr :: AggOp -> Column Selection -> Column Reduction 

instance IsString (Column Selection) where 
    fromString s = Column s 

data Query (a :: Sz) where 
    Table :: Schema -> Query Selection 
    Select :: [Column a] -> Query b -> Query Selection 
    Update :: [Column a] -> Query b -> Query Selection 
    Where :: [Column Selection] -> Query Selection -> Query Selection 
    Group :: [Column Selection] -> Query Selection -> Query Reduction 

şunlarla imza Select/Update için başarısız yapmak istiyorum:

[Column Selection] -> Query Reduction -> Query Selection 

Ama bu bambaşka bir kutu var solucanlar ...

+1

'demek bu kodla sadece iyi "bir"' typechecks ve ' "a"' tam da 'Sütun 'Selection' ait türetilmiş türü. Daha sonra '' '[' '' '' '' '' '' '' '' '' '' ['' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' yazın. Bir şey işe yaramazsa, lütfen hangi ifadenin belirsizliğe ve gerçek hatanın ne olduğuna neden olduğunu belirtin. Herhangi bir yerde 'from' veya' tbl' tanımlı değilsiniz, bu yüzden belki de bu işlevin hataları ile ilişkilidir. – user2407038

+0

sağa ama '[a] 'ı seçin tbl'den $ * yok * typecheck. –

+0

'den = table' ve 'sofra kaşığı = Şema {adı = Sadece "tbl" spektrumu = [Kolon, "a", Sütun, "b"]}' –

cevap

6

derleyici için size belirsiz bir tip hata vermek için doğrudur Select ["a"] - SelectionSelection argümanı olarak seçilebilir. Bu tam olarak amaçlanan davranış.

Ne istiyorsun şudur: bunu gerektiren aksine bu, derleyici "x" :: Column _ aslında "x" :: Column Selection olması gerektiğini anlaması sağlayacak

instance (x ~ Selection) => IsString (Column x) where 
    fromString = Column 

.

Select [mean "a"] tamamen farklı bir durumdur - mean :: Column Selection -> Column Reduction beri mean kuvvetlerin bu tür durumda olması nedeniyle örnek seçimi, o "a" :: Column Selection gerçekleşmeden önce derleyici bilir.