[Haskell-cafe] Fwd: Attempt at defining typeful primary key/foreign
key relationships
Justin Bailey
jgbailey at gmail.com
Mon Dec 31 15:30:41 EST 2007
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 <jgbailey at gmail.com>
Date: Dec 31, 2007 12:25 PM
Subject: Attempt at defining typeful primary key/foreign key relationships
To: haskelldb-users at lists.sourceforge.net
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
More information about the Haskell-Cafe
mailing list