From: Justin B. <jgb...@gm...> - 2008-01-30 18:01:23
|
All, project doesn't easily let me add a few columns to an existing query (or take a few columns away). Instead, each use of project requires me to build the entire list of columns I'd like to pass on by hand. Before I go further, if there is a way to do that, please let me know. An example of what I'd like to do is below. Imagine I want to add a "selected" boolean column to my query. select_customers = do cust <- table customers project ( (selectedField <<- False) # cust) So I get all the columns in my customers table, plus the "selected" column. Unfortunately the code above doesn't work. cust has type "Rel r", and project wants a "Record r", so I originally tried something like: select_customers = do let toRec :: Rel r -> Record r toRec _ = undefined ... project (unRel cust) But project needs to recover the "Expr" values associated with 'r' and this fails. I then came up with this solution, which lets me add columns at the head of a query: class RecoverExpr a b where toExpr :: a -> b instance RecoverExpr RecNil RecNil where toExpr rec = RecNil instance (FieldTag f, RecoverExpr r r) => RecoverExpr (RecCons f (Expr b) r) (RecCons f (Expr b) r) where toExpr ~rec@(RecCons _ r) = RecCons (attribute . fieldName $ recField $ rec) (toExpr r) recField :: RecCons f a b -> f recField _ = undefined rest :: (RecoverExpr r r) => Rel r -> r rest qry = let unRel :: Rel r -> r unRel _ = undefined in toExpr . unRel $ qry Then I can write: select_customers = do cust <- table customers_tbl ... project (selectField <<- False # (rest cust)) And it actually works. However, it seems over-engineered. My questions are: 1) Is there a way to make project behave like I want without these tricks? 2) If not 1, would it make more sense for the Query monad to pack around the original Expr values? 3) If not 2, how can the solution above be better? I'd like to extend it to adding/removing arbitrary columns and more control over column order. Thanks for any and all thoughts! Justin p.s. Sorry for the spam on cafe - I accidently sent this there first ... |
From: <bri...@cs...> - 2008-01-30 20:42:52
|
On Jan 30, 2008, at 19:01 , Justin Bailey wrote: > All, > > project doesn't easily let me add a few columns to an existing query > (or take a few columns away). Instead, each use of project requires me > to build the entire list of columns I'd like to pass on by hand. > Before I go further, if there is a way to do that, please let me know. No, there is no existing way to achieve this. Indeed, it's one of the =20= most common complaints about HaskellDB :-) > An example of what I'd like to do is below. Imagine I want to add a > "selected" boolean column to my query. > > select_customers =3D do > cust <- table customers > project ( (selectedField <<- False) # cust) > > So I get all the columns in my customers table, plus the "selected" > column. Unfortunately the code above doesn't work. > > cust has type "Rel r", and project wants a "Record r", so I originally > tried something like: > > select_customers =3D do > let toRec :: Rel r -> Record r > toRec _ =3D undefined > ... > project (unRel cust) > > But project needs to recover the "Expr" values associated with 'r' and > this fails. I then came up with this solution, which lets me add > columns at the head of a query: > > class RecoverExpr a b where > toExpr :: a -> b > > instance RecoverExpr RecNil RecNil where > toExpr rec =3D RecNil > > instance (FieldTag f, RecoverExpr r r) =3D> RecoverExpr (RecCons f > (Expr b) r) (RecCons f (Expr b) r) where > toExpr ~rec@(RecCons _ r) =3D RecCons (attribute . fieldName $ > recField $ rec) (toExpr r) > > recField :: RecCons f a b -> f > recField _ =3D undefined > > rest :: (RecoverExpr r r) =3D> Rel r -> r > rest qry =3D > let unRel :: Rel r -> r > unRel _ =3D undefined > in toExpr . unRel $ qry > > Then I can write: > > select_customers =3D do > cust <- table customers_tbl > ... > project (selectField <<- False # (rest cust)) > > And it actually works. However, it seems over-engineered. My =20 > questions are: > > 1) Is there a way to make project behave like I want without these =20= > tricks? I doubt that there is. In general, manipulating record types with =20 Haskell's roundabout type level programming is messy, there's no =20 avoiding that. > 2) If not 1, would it make more sense for the Query monad to pack > around the original Expr values? Hmm, wouldn't it need to carry those through arbitrary query =20 computations? > 3) If not 2, how can the solution above be better? I'd like to extend > it to adding/removing arbitrary columns and more control over column > order. The best way to do it would be to add powerful record types to =20 Haskell... You may want to look at HList, http://homepages.cwi.nl/~ralf/HList/ =20 I'm not sure how much HList can do now, perhaps they have added =20 things since they wrote the paper. There might be some nice record =20 manipulation stuff there that you could use. Porting HaskellDB to use =20= HList instead of its own records would be nice, if the HList code is =20 in good shape. > Thanks for any and all thoughts! > > Justin > > p.s. Sorry for the spam on cafe - I accidently sent this there =20 > first ... /Bj=F6rn |
From: Alain C. <al...@po...> - 2008-01-30 22:56:15
|
Björn Bringert a écrit : > On Jan 30, 2008, at 19:01 , Justin Bailey wrote: > >> All, >> >> project doesn't easily let me add a few columns to an existing query >> (or take a few columns away). Instead, each use of project requires me >> to build the entire list of columns I'd like to pass on by hand. >> Before I go further, if there is a way to do that, please let me know. > > No, there is no existing way to achieve this. Indeed, it's one of the > most common complaints about HaskellDB :-) > > >> 3) If not 2, how can the solution above be better? I'd like to extend >> it to adding/removing arbitrary columns and more control over column >> order. > > The best way to do it would be to add powerful record types to Haskell... > > You may want to look at HList, http://homepages.cwi.nl/~ralf/HList/ > <http://homepages.cwi.nl/%7Eralf/HList/> I'm not sure how much HList > can do now, perhaps they have added things since they wrote the paper. > There might be some nice record manipulation stuff there that you > could use. Porting HaskellDB to use HList instead of its own records > would be nice, if the HList code is in good shape. > Hi, The HList library compiles with ghc-6.8.2, and seems to be maintained. Indeed it would be a great idea to use it instead of HaskellDB's own heterogeneous list system. Alain |