Ich habe zwei GADTs, die ich verwende, um eine SQL EDSL zu modellieren. Um den Client sauber und einfach gegenüber dem API zu halten, möchte ich OverloadedStrings
verwenden, um String-Literale in eine Column Selection
zu konvertieren.So lösen Sie die Mehrdeutigkeit in meinen GADTs
Daher können Sie einfach
select ["a", "b"] $ from tbl
statt für Abfragen
select [Column "a", Column "b"] $ from tbl
Das Problem ist, dass wählen Sie ermöglicht für beide Column Selection
s und Reduction
s zu ermöglichen, geben Sie die Aggregationen auszuführen.
mean :: Column Selection -> Column Reduction
select :: [Column a] -> Query b -> Query Selection
select [mean "a"] $ from tbl
und somit sind die Saiten in diesem Zusammenhang von [Column a]
zweideutig. Aber select [mean "a"] $ from tbl
ist gültig, da mean
den erforderlichen Kontext bereitstellt, um zu folgern, dass das Zeichenfolgenliteral eine Spaltenauswahl ist.
Kann jemand einen Ausweg aus dieser Unordnung empfehlen?
Mein aktueller Code (irrelevant Instanzen weggelassen)
{-# 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
Ich würde auch die folgende Signatur mag nicht für Select
/Update
machen:
[Column Selection] -> Query Reduction -> Query Selection
Aber das ist eine ganz andere Dose von Würmern ...
'mittlere" a "' typechecks ganz gut mit diesem Code, und der abgeleitete Typ des '" a "' ist genau 'Spalte' Selection '. Dann ist der Typ von 'Select [mean" a "]' 'Query b -> Query 'Selection'. Wenn etwas nicht funktioniert, bitte genau angeben, welcher Ausdruck die Mehrdeutigkeit verursacht und was der tatsächliche Fehler ist. Sie haben '' '' '' '' '' '' '' '' '' '' tbl nicht definiert, ist der Fehler möglicherweise mit diesen Funktionen verbunden. – user2407038
rechts, aber 'wählen [" a "] $ from tbl' does * not * typecheck. –
'from = Table' und' tbl = Schema {name = Nur "tbl", spec = [Spalte "a", Spalte "b"]} ' –