
I want to implement generic comparison on top of syb-with-class, and based on looking at syb, it seems I could base it on something like gzipWithQ from syb's Data.Generics.Twins. However, there's no Data.Generics.SYB.WithClass.Twins. So I set out to see if I can write one myself (well, one with just enough stuff to support gzipWithQ anyway) Here's what I've got so far: http://hpaste.org/49168 The problem is that GHCi seems to be somewhat confused, or at least confusing, about the type of gzipWithQ here. When I ask with :t, it reports the type as: gzipWithQ :: (Data ctx a2, Data ctx a3, Data ctx a) => Proxy ctx -> (forall a0. Data ctx a0 => a0 -> forall a1. Data ctx a1 => a1 -> r) -> a2 -> a3 -> [r] If I actually replace gzipWithQ's annotated type with this, GHCi will reject the program. And in any case with GenericQ being defined as "type GenericQ ctx r = Data ctx a => a -> r", isn't this closer to gzipWithQ's type with the type synonyms expanded? gzipWithQ :: forall ctx a r. Data ctx a => Proxy ctx -> (Data ctx a0 => a0 -> (Data ctx a1 => a1 -> r)) -> (Data ctx a2 => a2 -> (Data ctx a3 => a3 -> [r])) (GHCi accepts this as gzipWithQ's type so I assume it's the same one. I assume those class constraints after the => come with implicit foralls? Because it seems to mean the same thing if I put foralls in there) I have no idea how to even start figuring out how to make gzipWithQ and its type work. I only got this far by copying code from Data.Generics.Twins and passing down the proxy parameter and/or context type parameter (is it even possible for this approach to work?). What I can tell is that GHCi will still change the type like that even if gzipWithQ = undefined, so I'll have to change the type and not just the body of the function. Is this the kind of thing that all those newtypes in Data.Generics.Twins are for? Should I read up on type theory?