[Haskell-cafe] Going insane over overlapping instances
aovieth at gmail.com
Sun May 22 18:12:40 UTC 2016
You could eliminate the JSON constructor from your servant types by using
it in the aeson instance for Foo itself:
instance ToJSON Foo where
toJSON = toJSON . JSON
instance FromJSON Foo where
parseJSON = fmap (\(JSON t) -> t) . parseJSON
This way, JSON is used only where it's relevant: not in the servant types,
but in the aeson instances. It gives the programmer a way to get them for
HasStructParser types at pretty much no cost. I don't think duplicate
instances are a concern here. If you want to use an existing aeson-equipped
type in your servant routes, but redefine those aeson instance via
HasStructParser, then make a newtype. In my opinion it's a good idea to
have new types for servant inputs anyway, to make very clear the provenance
of these values.
On Sun, May 22, 2016 at 1:05 PM, Brian Hurt <bhurt at spnz.org> wrote:
> This is driving me nuts.
> So I have a type class HasStructParser I've defined. Details are
> irrelevant except that if you have HasStructParser defined, then ToJSON is
> also defined. So I have:
> instance HasStructParser s => ToJSON s where
> But now, any type that defines ToJSON any other way causes an Overlapping
> Instances error to happen- the conflict being between the real ToJSON
> implementation and the one deriving from HasStructParser- this despite the
> fact that there is no implementation for HasStructParser for the given type.
> Now, I don't want to allow Overlapping Instances because if there are
> *real* overlapping instances, I want that to be an error. For instance, if
> a structure did implement HasStructParser and some other implementation of
> ToJSON, I want to know.
> I suppose I could go:
> newtype JSON a = JSON a
> instance HasStructParser s => ToJSON (JSON s) where ...
> But this strikes me as being ugly- now I have to add pointless JSON
> constructors everywhere I want to convert to (or from) JSON. And this also
> pollutes my type signatures all over the place- now I can't write a servant
> endpoint type like:
> :<|> "foo" :> "bar" :> Get '[JSON] [Foo]
> I have to write:
> :<|> "foo" :> "bar" :> Get '[JSON] [JSON Foo]
> And, of course, if I want to have multiple different types of outputs, now
> we're off to the races.
> So my question is, is there a way to do this without throwing the baby out
> with the bath water (turning on overloaded instances) or being seriously
> ugly? Or am I just screwed?
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Haskell-Cafe