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 |