Allowing duplicate instances in GHC 6.4

Keean Schupke k.schupke at
Fri Mar 25 18:09:09 EST 2005

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.


More information about the Glasgow-haskell-users mailing list