[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