Robert van Herk wrote:

Keean Schupke wrote:

Just thought I ought to point out that all this is only necessary if the datasources may return different types... If you want them to return the same type you only need:

instance (Datasource l k v,Datasource r k v) => Datasource (JoinedDS l r) k v ...

As both datasources have the same key and value types, you then choose which 'v' to return at the value level.


Nono, the datasources I have implemented are a type safe means to extract (key,value) pairs from a data store. The idea is that this way, in a type safe fashion, e.g. database access can be abstract.

I use HaskellDB as the database access layer, and then define a datasource instance for any given database, so that the user does not need to think about the details of the actual database access: he can just read and write from the datasource, and the datasource will make sure the actual queries will be executed.

My idea now was that if I have 2 databases, and I construct datasources for them, it would be really cool if I was able to unite them, so that the programmer in the end could talk two 1 datasource, that allowed for accessing the 2 databases at one entry point. This was what I was making the JoinedDS for.

So, suppose I have 2 datasources for two different databases. One may have keys:
data KeysOfDS1 = KDB1_Table1 Int
| KDB1_Table2 Int


and values
data ValuesOfDS1 = VDB1_Table1 (Int,Int,String)
                               | VDB2_Table2 (Int,Int,String)

and the other one:
data KeysOfDS2 = KDB2_Table1 String
                           |  KDB2_Table2 String
data ValuesOfDS2 = VDB2_Table1 (String, Float)
                               | VDB2_Table2 (String, Float, Int)

Now, these datastructures correspond to the actual tables in the database. My toolset will generate datasources for these types, thus we have instances:

instance Datasource Database1 KeysOfDS1 ValuesOfDS1
instance Datasource Database2 KeysOfDS2 ValuesOfDS2

and the cool thing would be, to combine these two datasources at a higher level in my datasources graph, so that I would have 1 datasource that found out by itself which actual datasource to use, thus:

x::JoinedDS
x = JoinedDS db1 db2 -- where dbx is a datasource Databasex KeysOfDSx ValuesOfDSx


Now, I would want the user to be able to read both KeysOfDS1 (which would yield a ValuesOfDS1) as well as KeysOfDS2 (which would yield a ValuesOfDS2) from x.

Herefore, I need the instances mentioned before:
instance (Datasource l k v) => Datasource (JoinedDS l r) k v where
dsread (JoinedDS l r) k = let (l, v) = dsread l k in (JoinedDS l r, v)
instance (Datasource r k v) => Datasource (JoinedDS l r) k v where
dsread (JoinedDS l r) k = let (r, v) = dsread r k in (JoinedDS l r, v)

But this, thus, yields duplicate instance errors, which I don't like :-).

Robert

P.S. Sorry for any typos, I am enjoying a rather nice bottle of wine :-).

Thats because they overlap in 'k'. However you can change the fundep:

>class Datasource s k v | s -> k v
>instance Datasource DB1 K1 V1
>instance Datasource DB2 K2 V2
>instance (Datasource l k' v',TypeEq k k' z,Datasource' z l r k v) => Datasource (JoinedDS l r) k v where
>
>class Datasource' z l r k v | z l r -> k v
>instance Datasource l k v => Datasource' TTrue l r k v
>instance Datasource r k v => Datasource' TFalse l r k v


Here I have used TypeEq from the HList library to determine if the type parameter k is the same type as the k' from datasource l. This lets k determine which instance from the other class gets used.

   Keean.

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Reply via email to