1

I'm using Aeson for some client-server stuff that I'm doing, encoding ADTs as Json. I'm using Data.Aeson.TH to generate the toJSON instances I need, but the instances generated for Map types are really ugly and awful to deal with.

I've defined my own, simpler encoding which just treats them as lists:

instance (ToJSON a, ToJSON b) => ToJSON (Map a b) where
  toJSON m = toJSON $ toList m

Naturally, when I use this in my code, I get a Duplicate instance declarations error.

Is there a way to resolve this? I need to either tell Template Haskell NOT to generate the ToJson instance for Map, or I need to tell GHC to ignore that instance and use the one I supply. Can either of these be done?

Note that this isn't an "overlapping-instances" problem. I want to completely throw out the one instance, not mix it with the other one.

jmite
  • 8,171
  • 6
  • 40
  • 81

1 Answers1

4

To tell GHC to ignore library-provided instance and use your own instead, you can wrap Map in a newtype:

newtype PrettyMap key val = PrettyMap (Map key val)
instance (ToJSON a, ToJSON b) => ToJSON (PrettyMap a b) where
  toJSON (PrettyMap m) = toJSON $ toList m

Another solution is to really use OverlappingInstances:

data MyData = ...
$(deriveToJSON ... ''MyData)

instance ToJSON (Map Text MyData) where
    toJSON = toJSON . toList
max taldykin
  • 12,459
  • 5
  • 45
  • 64
  • Hmm, I'll try the type-wrapper. Thanks! – jmite Feb 17 '14 at 01:57
  • As it turns out, I'm an idiot. I had explicitly derived a ToJSON for Map, which I then got rid of, fixing everything. Either way, your answer was informative, so thanks! – jmite Feb 17 '14 at 06:57