
At Mon, 20 Jun 2011 09:57:38 +0200, José Pedro Magalhães wrote:
class JSON1 a r | a -> r toJSON1 :: a -> r
instance (JSON a) => JSON1 (S1 NoSelector (K1 c a)) [Value] where toJSON1 (M1 (K1 a)) = [toJSON a]
instance (Selector x, JSON a) => JSON1 (S1 x (K1 c a)) [(String, Value)] where toJSON1 s@(M1 (K1 a)) = [(nameOf s undefined, toJSON a)] where nameOf :: S1 c f p -> c -> String nameOf _ c -> selName c
The key piece of magic I need here (and in so many other places) is to be able to do one thing at the type level if x is a particular type (e.g., NoSelector) or sometimes one of a small number of types, and to do something else if x is any other type.
Right. I think this is often essential.
One thing you could do to help in this specific case would be to use a different M1 tag--e.g., M1 S ... for selectors and M1 NS ... for fields without selectors (or K1 NS). I presume you've already considered this and/or it's too late to make such a change. (Or to move the distinction up to the constructor with two different constructor tags, CR and CN for record and no-record.) Anyway, as you mention, there are other situations where you still need Overlapping/UndecidableInstances. David