From: Justin B. <jgb...@gm...> - 2007-12-31 20:58:26
|
Small correction - the extensions listed at the bottom weren't necessary. I had attempted to define a relationship among tables automatically as: instance (HasField fk child, HasField pk parent, HasRelation pk fk) => HasRelation parent child But that was redundant with the signature on relation. Removing it allowed me to remove all extensions except MultiParameterTypeClasses. Justin ---------- Forwarded message ---------- From: Justin Bailey <jgb...@gm...> Date: Dec 31, 2007 12:25 PM Subject: Attempt at defining typeful primary key/foreign key relationships To: has...@li... All, As part of my data model, I'd like to say there is a primary key/foreign key relationship between two tables/queries. Right now I only want to do this to capture some extra-query information that I'm using for code generation - I don't intend it to actually affect queries generated, though I'd like to go there eventually. I define a class which says there is a relation: class HasRelation pk fk I define a type which holds relation values: data Relation a pk fk p c = Relation { ... } Relation values can only be constructed by a function with appropriate constraints on it: relation :: (HasRelation pk fk, HasField pk parent, HasField fk child) => Attr pk a -> Attr fk a -> Rel parent -> Rel child -> Relation a pk fk parent child relation primaryKey foreignKey prnt chld = Relation .... As an example, if I have tables Orders and LineItems, both with field order_id, I can establish a relationship by first defining an instance: instance HasRelation Orders.Order_id LineItems.Order_id I can then create a relation value between the two: orders <- table Orders.orders lineItems <- table LineItems.lineItems let r1 = relation Orders.order_id LineItems.order_id orders lineitems Note these types would be defined using DBDirect, so Order_id as a type with one constructor, lineItems has type "Table ...", etc. If I try to define an incorrect relation (wrong fields, fields in the wrong order, etc), then the above will not compile, which is just what I want. If you've read this far, I've not done any type-level programming or even played much with classes and instances before so I'd like to know if the approach makes sense. I took most of my inspiration from the HasField class in the HDBRec module. 1) Could this be simpler? Any obvious deficiencies? 2) I had to enable a number of extensions (though all of these are also enabled by haskelldb) - FlexibleInstances, FlexibleContexts, UndecidableInstances and OverlappingInstances. Should I be worried? 3) It's possible to define relationships among any two types. How can I limit that to 1) attributes with 2) the same type? Would I have to define an Attr typeclass, parallel to the Attr type? Thanks for any and all feedback. Happy New Year! Justin |