[Template-haskell] Is there an easier way to write [| $(..) $(..) $(..) |] ?

Marc Weber marco-oweber at gmx.de
Mon Jun 30 17:47:29 EDT 2008


Right now I'm spending some time on exploring how haskell could be used
to model a small in memory only RDBM system. (Final goal is to use it
with HAppS state etc..)

A db description looks like this:

$(let cds = defaultTable {
               tblName = "cds"
               , columns = [ ("cdId", conT ''Int) , ("title", conT ''Int) ]
               , primary = PrimaryUniq [ "cdId" ] (MaxPKPlusOne 10)
               , indexes = [ Index "title" [] ]
               , tblStates = [ ( "nextCdId", [t| Int |], [| 0 |] ) ]
           }

      tracks = let
            a="a"
            in defaultTable {
            tblName = "tracks"
            , columns = [ ("trackId", conT ''Int )
                      , ("name", conT ''String)
                      , ("cd", conT ''Int) -- foreign key 
                      ]
            , primary = PrimaryUniq [ "cd", "trackId" ] 
                                    -- is there a nice way than using that many mkNameE 
                                    (SetSubPKPlusOne 5)
            , indexes = [ Index "cd" [ IndexUnique "trackId" ] ] --the id is uniq foreach cd 
            -- checks = [ foreignConstraint "cd" "cds" "id" ]
            -- triggers =  [ InsertUpdate  (Just ["cd"]) [| cdUpdateByPK ( updateNum_tracks (+1) ) . pk |]
                          -- DeleteUpdate  (Just ["cd"]) [| cdUpdateByPK ( updateNum_tracks (-1) ) . pk |] 
                          -- ]
                }
      db = defaultDB {
             dbName = "my"
           , tables = [ cds, tracks]
           , statistics = True
           }
 in createDB db)


instead of the MaxPKPlusOne you can also use your custom function to get
the next primary id:
[| \row -> withNextIdStateFromCds $ do s <- get; put (s+1); return s |]
This will get more complicated for sofisticated use cases
SetSubPKPlusOne. The primary key is made up of the cdId and the trackId.
Now I'd like to set the trackId to the smallest not yet used number.
This results in something like

row -> let cd = cdId row
       in let map = lookup cd (get index map here)
          in if null map then 1
             else (+1).fst.findMAx map

which is fine except that cdId and (get index map here) must use
functions defined by createDB. So the only way to write this is
cluttering everything up with $(varE $ mkName $ "cdId") which makes the
code less readable..

So my question is: Would it make sense to ask ghc to take an unkown
function, but instead of complaining rewrite it as varE $ mkName $ <name> ?

Maybe one easy solution to achievie this is make haskell-src output an
template haskell AST?

Then you can get nice looking and readable code and still have most of
the power of weriting template haskell ?

Anyone thought about this?

Mmh still thinking about how the query language should look like.
I have something like printf syntax in mind...

$(query "id > ?1 AND ?2 == text ") 7 "text" ..

Marc Weber


More information about the template-haskell mailing list