
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
participants (1)
-
Emil Axelsson