2016-03-02 24 views
9

Tôi có hai GADT mà tôi đang sử dụng để tạo mô hình cho SQL EDSL. Để giữ khách hàng đối diện với api rõ ràng và đơn giản, tôi muốn sử dụng OverloadedStrings để chuyển các chuỗi ký tự thành một số Column Selection.Cách giải quyết sự mơ hồ trong GADT của tôi

Vì vậy, bạn có thể chỉ cần gõ

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

thay vì

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

Vấn đề là chọn cho phép cả hai Column Selection s và Reduction s để cho phép truy vấn thực hiện quy tụ.

mean :: Column Selection -> Column Reduction 

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

và do đó các chuỗi không rõ ràng trong ngữ cảnh [Column a] này. Nhưng select [mean "a"] $ from tbl là hợp lệ kể từ mean cung cấp ngữ cảnh cần thiết để suy ra rằng chuỗi ký tự là một lựa chọn cột.

Có ai có thể giới thiệu cách thoát khỏi mớ hỗn độn này không?

mã hiện tại của tôi dưới đây (trường hợp không liên quan bỏ qua)

{-# 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 

Tôi cũng muốn làm cho chữ ký sau thất bại cho Select/Update:

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

Nhưng đó là một toàn bộ lon khác giun ...

+1

'có nghĩa là" một "typechecks tốt với mã này, và loại suy luận của' "a" 'là chính xác' Cột 'lựa chọn'. Sau đó, kiểu 'Select [mean" a "]' là 'Query b -> Query 'Selection'. Nếu một cái gì đó không hoạt động, vui lòng bao gồm chính xác biểu thức nào gây ra sự mơ hồ và lỗi thực tế là gì. Bạn đã không định nghĩa 'from' hoặc' tbl' ở bất kỳ đâu, vì vậy có lẽ lỗi này liên quan đến các hàm đó. – user2407038

+0

phải nhưng 'chọn [" a "] $ từ tbl' không * không * typecheck. –

+0

'từ = Bảng' và 'tbl = Lược đồ {name = Chỉ" tbl ", spec = [Cột" a ", Cột" b "]}' –

Trả lời

6

Trình biên dịch là chính xác để cung cấp cho bạn một lỗi loại không rõ ràng cho Select ["a"] - ví dụ IsString (Column Selection) có thể được chọn chỉ nếu một đối số ưu tiên đối số là Column được biết là Selection. Đây chính là hành vi dự định.

gì bạn muốn là như sau:

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

này sẽ cho phép trình biên dịch để suy ra rằng "x" :: Column _ thực sự phải "x" :: Column Selection, như trái ngược với đòi hỏi nó.

Select [mean "a"] là một tình huống hoàn toàn khác - kể từ mean :: Column Selection -> Column Reduction, trình biên dịch biết, trước khi lựa chọn trường hợp xảy ra, "a" :: Column Selection, vì loại mean buộc điều này xảy ra.

Các vấn đề liên quan