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
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.
More information about the Glasgow-haskell-users