[Haskell-cafe] Selecting overlapping instances

Emil Axelsson emax at cs.chalmers.se
Thu Feb 22 04:40:48 EST 2007


Hello!

I have a problem with overlapping instances for which I already know a 
workaround. However, I'm still curious to know if there isn't a simpler solution 
available. I have a feeling that -fallow-incoherent-instances might be the 
answer, but I can't get it to work.

In the code at the end of the message, (Block w n s e) is a representation of a 
geometrical block whose west-/north-/south-/eastern edge has type w/n/s/e 
respectively. (*||*) composes two blocks horizontally and (*=*) composes 
vertically. In this simplified example, there is only one primitive block -- 
unitBlock.

Now, I want to be able to make grids of unitBlock:s where the edges can have any 
type that can be obtained using (,) and (). This is what the Grid class attempts.

The program compiles fine until I add the test program

> test :: Block ((),()) ((),()) ((),()) ((),())
> test = grid

which raises an "Overlapping instances" error. What I would like is for the 
compiler to pick *either* of the two matching instances first, and then the 
other one, because in this particular case, it doesn't matter which one it picks 
first.

The workaround is to explicitly pick an order by giving the additional instance 
(requires -fallow-overlapping-instances):

> instance ( Grid x1 y1
>          , Grid x1 y2
>          , Grid x2 y1
>          , Grid x2 y2
>          ) => Grid (x1,x2) (y1,y2)
>   where
>     grid = grid *||* grid

Is there any way to make this work without adding this last instance?

Thanks!

/ Emil



--------------------------------------------------------

> data Block w n s e = Block
> 
> (*||*) :: Block w1 n1 s1 x -> Block x n2 s2 e2 -> Block w1 (n1,n2) (s1,s2) e2
> (*||*) = undefined
> 
> (*=*) :: Block w1 x s1 e1 -> Block w2 n2 x e2 -> Block (w1,w2) n2 s1 (e1,e2)
> (*=*) = undefined
> 
> unitBlock :: Block () () () ()
> unitBlock = undefined
> 
> class Grid x y
>   where
>     grid :: Block x y y x
> 
> instance Grid () ()
>   where
>     grid = unitBlock
> 
> instance (Grid x1 y, Grid x2 y) => Grid (x1,x2) y
>   where
>     grid = grid *=* grid
> 
> instance (Grid x y1, Grid x y2) => Grid x (y1,y2)
>   where
>     grid = grid *||* grid




More information about the Haskell-Cafe mailing list