Ho due GADT che sto usando per modellare una SQL EDSL. Per mantenere il client di fronte api pulito e semplice, desidero utilizzare OverloadedStrings
per convertire valori letterali stringa su Column Selection
.Come risolvere l'ambiguità nei miei GADT
Pertanto è sufficiente digitare
select ["a", "b"] $ from tbl
invece di
select [Column "a", Column "b"] $ from tbl
Il problema è che select consente sia Column Selection
s e Reduction
s per consentire per le query che eseguono aggregazioni.
mean :: Column Selection -> Column Reduction
select :: [Column a] -> Query b -> Query Selection
select [mean "a"] $ from tbl
e quindi le corde sono ambigui in questo contesto di [Column a]
. Ma select [mean "a"] $ from tbl
è valido dal mean
fornisce il contesto necessario per dedurre che la stringa letterale è una selezione di colonne.
Qualcuno può consigliare un modo per uscire da questo pasticcio?
Il mio codice corrente al di sotto (casi irrilevanti omessi)
{-# 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
Vorrei anche fare la seguente firma falliscono per Select
/Update
:
[Column Selection] -> Query Reduction -> Query Selection
ma questa è tutta un'altra lattina di worm ...
'significa" a "' typechecks bene con questo codice, e il tipo dedotto del '" a "' è precisamente 'Colonna 'Selezione'. Quindi il tipo di "Seleziona [significa" a "]" è "Query b -> Query" Selezione ". Se qualcosa non funziona, includi con precisione quale espressione causa l'ambiguità e qual è l'errore effettivo. Non hai definito 'from' o' tbl' ovunque, quindi forse l'errore è legato a quelle funzioni. – user2407038
right ma 'select ["a"] $ da tbl' fa * not * typecheck. –
'from = Table' e' tbl = Schema {name = Just "tbl", spec = [Colonna "a", Colonna "b"]} ' –