From: Justin B. <jgb...@gm...> - 2008-03-25 21:26:13
|
On Tue, Mar 25, 2008 at 2:08 PM, Bjorn Bringert <bj...@br...> wrote: > Hi Justin, > > this is a very good observation, and a good argument for why using a > Monad for constructing queries is a bad idea. Heffalump has proposed > an alternative functional API which should make it easier to avoid > problems like this. Do you have a link to that? I would be interested in looking at it. > But Monads should be associative (see > http://www.haskell.org/haskellwiki/Monad_Laws for a little bit of > explanation), so this should be equivalent to: > > do > table1 > aggregate1 > table2 > aggregate2 > rest > > Which gives you the result that you didn't want. The conclusion is > that with the current API, you can't compose aggregate queries the way > you want. Queries in the monadic interface should be read line by A very good point. Aggregrates are weird in SQL anyways so I'm not surprised this shows up as a bug. > I'm thinking that it should be possible to get around this problem by > adding an explict cartesian product operator to use instead of >>= / > do. But then we are well on our way to a non-monadic interface. Can you think of a way to inject a primitive query into an existing relation? I tried to write a "seedQuery" function but it gave me an assertion failure in optimize: seedQuery :: (PrimQuery, Rel r) -> Query (Rel r) seedQuery (prim, rel) = Query (\(x, qry) -> (rel, (x, prim))) The signature for seedQuery follows from runQueryRel in Query.hs, so you would use it as: do x <- seedQuery . runQueryRel $ { do ... } y <- seedQuery . runQueryRel $ { do ... } rest If this function worked, a query could be built in isolation and the problem would be avoided (and maybe even still preserving associativity?). Justin |