[Haskell-cafe] Going insane over overlapping instances

Alexander Vieth aovieth at gmail.com
Sun May 22 18:12:40 UTC 2016


Hi Brian,

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.

Alex

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?
>
> Brian
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20160522/1eda4fbc/attachment.html>


More information about the Haskell-Cafe mailing list