Allowing duplicate instances in GHC 6.4

Robert van Herk rherk at cs.uu.nl
Fri Mar 25 14:21:04 EST 2005


Keean Schupke wrote:

> Robert van Herk wrote:
>
>> Hi all,
>>
>> I need to use duplicate instances. I read in the documentation on GHC 
>> 6.4, that overlapping class instances checks are lazy instead of 
>> gready in 6.4. However, my code still gives duplicate instance errors 
>> when compiling in GHC 6.4.
>>
>> Is the duplicate instance check still gready? Is there a way to 
>> overwrite that behaviour?
>>
>> Right now, I have two instance of a class Datasource. Datasource 
>> allows the user to read (key,value) pairs.
>>
>> class Datasource ds k v where
>> ...
>>
>> Now, I wanted to make a special datasource that combines two 
>> datasources, namely
>>
>> data JoinedDS left right = JoinedDS left right
>> instance (Datasource left k v) => Datasource (JoinedDS left right) k 
>> v where
>> ...
>>
>> instance (Datasource right k v) => Datasource (JoinedDS left right) k 
>> v where
>> ...
>>
>> The idea is that when you combine 2 datasources in one JoinedDS, the 
>> user can read both types from the JoinedDS. I do not need to allow to 
>> combine 2 different datasources that have the same types of 
>> (key,value) pairs, so the duplicate instances will not occur and when 
>> they do, this will be by mistake. Hence, the two premisses in the 
>> instance declaration will never be fulfilled both at the same time 
>> and I do not want a duplicate instance error here.
>>
>> Is there a  solution to this problem?
>>
> To resolve overlap the HEAD of the instance must be different... Might 
> I suggest:
>
> -- as value depends on source and key, requires functional dependancy
> class Datasource s k v | s k -> v ...

Yes, I already had that, forgot to mention it though...

> data JoinedDS l r = JoinedDS l r
> instance (Datasource l k v1,Datasource r k v2) => Datasource (JoinedDS 
> l r) k (v1,v2) ...
>
> Now a joined datasource resturns a pair of values instead of a single 
> value.

Yes, but this is not what I want. I want to be able to give a key that 
either the left or the right data source would take, and then return the 
appropriate value. Thus: if I pass it a key that would normally go into 
l, I want the value l returns me to be returned, and if I pass it the 
key that would normally go into r, I want to return the value r returns me.

The datasource class has a function dsread :: ds -> k -> (ds, v) -- read 
may have a side effect
Thus I want want to do something like:
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)

It would be perfectly okay to me when the compiler would complain if the 
key and value that go into l and r are the same, but for any useful 
purpose I can think of (e.g. glueing two database couplings together, 
since I also made a Datasource instance for database access), this will 
not happen and the duplicate instances should not really occur, since 
the context of the instances makes sure only 1 will be possible.

However, GHC only looks at the RHS (thus: Datasource (JoinedDS l r) k v) 
and then decides that both instances are the same.

So, my question was: how to overcome this.

Thanks,
Robert




More information about the Glasgow-haskell-users mailing list