[Haskell-cafe] Improving 'project'

Justin Bailey jgbailey at gmail.com
Wed Jan 30 13:00:38 EST 2008


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

Thanks for any and all thoughts!


More information about the Haskell-Cafe mailing list