Avoiding repeated instance declarations in Haskell The 2019 Stack Overflow Developer Survey Results Are InRemoving repetitions from multiple instance declarationsGetting started with HaskellWhat is Haskell actually useful for?Large-scale design in Haskell?Speed comparison with Project Euler: C vs Python vs Erlang vs Haskellhaskell — any way to generate “deriving” instances for roughly-tuple-isomorphic data types?Why can't GHC derive instances for Monoid?Using custom instance when deriving an instance via GeneralizedNewtypeDerivingHow to make aliases with yaml library in Haskell?Custom ToJSON instance for Persistent KeyWhat does deriving do/mean in Haskell?

Origin of "cooter" meaning "vagina"

What is the meaning of the verb "bear" in this context?

Are there incongruent pythagorean triangles with the same perimeter and same area?

What do the Banks children have against barley water?

Which Sci-Fi work first showed weapon of galactic-scale mass destruction?

Is an up-to-date browser secure on an out-of-date OS?

Can one be advised by a professor who is very far away?

Why do some words that are not inflected have an umlaut?

Multiply Two Integer Polynomials

Why do UK politicians seemingly ignore opinion polls on Brexit?

Can we generate random numbers using irrational numbers like π and e?

FPGA - DIY Programming

Am I thawing this London Broil safely?

What is the closest word meaning "respect for time / mindful"

Apparent duplicates between Haynes service instructions and MOT

Did 3000BC Egyptians use meteoric iron weapons?

How to answer pointed "are you quitting" questioning when I don't want them to suspect

Does a dangling wire really electrocute me if I'm standing in water?

Is this app Icon Browser Safe/Legit?

Can you compress metal and what would be the consequences?

Does the shape of a die affect the probability of a number being rolled?

Protecting Dualbooting Windows from dangerous code (like rm -rf)

Does coating your armor in silver add any effects?

What did it mean to "align" a radio?



Avoiding repeated instance declarations in Haskell



The 2019 Stack Overflow Developer Survey Results Are InRemoving repetitions from multiple instance declarationsGetting started with HaskellWhat is Haskell actually useful for?Large-scale design in Haskell?Speed comparison with Project Euler: C vs Python vs Erlang vs Haskellhaskell — any way to generate “deriving” instances for roughly-tuple-isomorphic data types?Why can't GHC derive instances for Monoid?Using custom instance when deriving an instance via GeneralizedNewtypeDerivingHow to make aliases with yaml library in Haskell?Custom ToJSON instance for Persistent KeyWhat does deriving do/mean in Haskell?



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








4















My question seems to be closely related to this
one.



My code parses a yaml file, rearanges the objects and writes a new yaml file. It works perfectly well, but there is a particularly ugly part in it.



I have to declare my data structures as instances of FromJson and ToJson like this:



instance FromJSON Users where
parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
instance ToJSON Users where
toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )


The problem is that I have to repeat this for 8 or so other cases:



instance FromJSON Role where
parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
instance ToJSON Role where
toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

...
...


I could not figure out how to avoid this repetition. Is there some method to declare the two functions just once (for example in a new class) and let all these data types derive from it?



Solution (see also accepted answer by dfeuer):



I personally like this solution. You'll need to add



-# language DerivingVia #-
-# language UndecidableInstances #-

newtype NP a = NP unNP::a

instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
parseJSON = fmap NP . genericParseJSON
(defaultOptions fieldLabelModifier = body_noprefix )

instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


Then you can declare the types like this:



data User = User ... deriving (Show, Generic)
deriving FromJSON via (NP User)
deriving ToJSON via (NP User)









share|improve this question






























    4















    My question seems to be closely related to this
    one.



    My code parses a yaml file, rearanges the objects and writes a new yaml file. It works perfectly well, but there is a particularly ugly part in it.



    I have to declare my data structures as instances of FromJson and ToJson like this:



    instance FromJSON Users where
    parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
    instance ToJSON Users where
    toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )


    The problem is that I have to repeat this for 8 or so other cases:



    instance FromJSON Role where
    parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
    instance ToJSON Role where
    toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

    ...
    ...


    I could not figure out how to avoid this repetition. Is there some method to declare the two functions just once (for example in a new class) and let all these data types derive from it?



    Solution (see also accepted answer by dfeuer):



    I personally like this solution. You'll need to add



    -# language DerivingVia #-
    -# language UndecidableInstances #-

    newtype NP a = NP unNP::a

    instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
    parseJSON = fmap NP . genericParseJSON
    (defaultOptions fieldLabelModifier = body_noprefix )

    instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
    toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


    Then you can declare the types like this:



    data User = User ... deriving (Show, Generic)
    deriving FromJSON via (NP User)
    deriving ToJSON via (NP User)









    share|improve this question


























      4












      4








      4


      1






      My question seems to be closely related to this
      one.



      My code parses a yaml file, rearanges the objects and writes a new yaml file. It works perfectly well, but there is a particularly ugly part in it.



      I have to declare my data structures as instances of FromJson and ToJson like this:



      instance FromJSON Users where
      parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
      instance ToJSON Users where
      toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )


      The problem is that I have to repeat this for 8 or so other cases:



      instance FromJSON Role where
      parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
      instance ToJSON Role where
      toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

      ...
      ...


      I could not figure out how to avoid this repetition. Is there some method to declare the two functions just once (for example in a new class) and let all these data types derive from it?



      Solution (see also accepted answer by dfeuer):



      I personally like this solution. You'll need to add



      -# language DerivingVia #-
      -# language UndecidableInstances #-

      newtype NP a = NP unNP::a

      instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
      parseJSON = fmap NP . genericParseJSON
      (defaultOptions fieldLabelModifier = body_noprefix )

      instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
      toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


      Then you can declare the types like this:



      data User = User ... deriving (Show, Generic)
      deriving FromJSON via (NP User)
      deriving ToJSON via (NP User)









      share|improve this question
















      My question seems to be closely related to this
      one.



      My code parses a yaml file, rearanges the objects and writes a new yaml file. It works perfectly well, but there is a particularly ugly part in it.



      I have to declare my data structures as instances of FromJson and ToJson like this:



      instance FromJSON Users where
      parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
      instance ToJSON Users where
      toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )


      The problem is that I have to repeat this for 8 or so other cases:



      instance FromJSON Role where
      parseJSON = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
      instance ToJSON Role where
      toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

      ...
      ...


      I could not figure out how to avoid this repetition. Is there some method to declare the two functions just once (for example in a new class) and let all these data types derive from it?



      Solution (see also accepted answer by dfeuer):



      I personally like this solution. You'll need to add



      -# language DerivingVia #-
      -# language UndecidableInstances #-

      newtype NP a = NP unNP::a

      instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
      parseJSON = fmap NP . genericParseJSON
      (defaultOptions fieldLabelModifier = body_noprefix )

      instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
      toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


      Then you can declare the types like this:



      data User = User ... deriving (Show, Generic)
      deriving FromJSON via (NP User)
      deriving ToJSON via (NP User)






      haskell instance dry






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 21 at 15:48







      fata

















      asked Mar 20 at 19:18









      fatafata

      234




      234






















          3 Answers
          3






          active

          oldest

          votes


















          3














          This is what the fairly new DerivingVia extension is for, among other things.



          -# language DerivingVia #-

          newtype NP a = NP unNP::a

          instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
          parseJSON = fmap NP . genericParseJSON
          (defaultOptions fieldLabelModifier = body_noprefix )

          instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
          toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


          Now, you can write



          deriving via (NP User) instance FromJSON User


          Or



          data User = ...
          deriving Generic
          deriving (FromJSON, ToJSON) via (NP User)


          and so on.



          This doesn't save a lot over leftaroundabout's answer as it is. However, once you add a definition of toEncoding, it starts to look worthwhile.



          Caution: I have tested none of this.






          share|improve this answer

























          • I see this as the most elegant solution until now. There is just a small typo here: ToJSON = should be toJSON =.

            – fata
            Mar 21 at 15:50



















          2














          Like,



          noPrefixParseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
          noPrefixParseJSON
          = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
          noPrefixToJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value
          noPrefixToJSON
          = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

          instance FromJSON User where parseJSON = noPrefixParseJSON
          instance ToJSON User where toJSON = noPrefixToJSON
          instance FromJSON Role where parseJSON = noPrefixParseJSON
          instance ToJSON Role where toJSON = noPrefixToJSON
          ...


          Sure this is still kind of repetitive, but I'd say this isn't any cause of worry any more.






          share|improve this answer

























          • It's a good idea to extract the function definitions but the main problem still remains in my opinion. Maybe a meta programming solution via template haskell is the correct way to go?

            – fata
            Mar 20 at 20:59


















          0














          If explicitly declaring all those similar instances proves too onerous, perhaps you could parameterize your datatypes with a phantom type like



          data User x = User aa :: Int, bb :: Bool deriving Generic

          data Role x = Role xx :: Int, dd :: Bool deriving Generic


          and then define a "marker" datatype like



          data Marker


          This datatype will only serve as a peg on which to hang instances like the following



          -# language UndecidableInstances #-
          instance (Generic (f Marker), GFromJSON Zero (Rep (f Marker))) => FromJSON (f Marker) where
          parseJSON = noPrefixParseJSON


          Would it be worth it? Likely not, because the definition of your datatypes becomes more complex. On the other hand, you could change aspects of the serialization by varying the marker, so you gain some flexibility.






          share|improve this answer

























          • That instance overlaps a lot. I think a newtype taking a phantom marker (or even a list of markers) would be a lot cleaner. That could also be useful for the DerivingVia approach I outlined in my answer, if you want to do a lot of type-level work up front.

            – dfeuer
            Mar 22 at 1:51











          • @dfeuer I believe it overlaps with more concrete types also parametrized with Marker, but the idea is that Marker will be used only with entities defined in the same module, and for those we wanted "uniform" instances anyway. A problem I see with the newtype is that if Role is nested within User, we also have to put the newtype there, which seems inconvenient.

            – danidiaz
            Mar 22 at 7:24












          • I'm pretty sure it will also affect instance resolution in some other circumstances. For example, suppose you want the instance for Const Int a, where a is neither specified nor inferred. Having your instance in scope will cause resolution to fail where it would otherwise succeed, because the compiler now wants to know that a is not the marker type.

            – dfeuer
            Mar 22 at 7:56











          • @dfeuer The GHC User Guide states that "It is fine for there to be a potential of overlap […] an error is only reported if a particular constraint matches more than one [instance]" downloads.haskell.org/~ghc/latest/docs/html/users_guide/… So, as long as we don't require FromJSON from a Const Int Marker in our program, we won't get any overlapping instances error.

            – danidiaz
            Mar 22 at 18:30











          • Huh .... It looks like I was overly optimistic about resolution without that instance. I'm pretty sure I've encountered situations where that hurt when messing around with Data.Constraint.Forall; I'll have to dig a bit further and see if I can produce a real example.

            – dfeuer
            Mar 22 at 20:09











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55268631%2favoiding-repeated-instance-declarations-in-haskell%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3














          This is what the fairly new DerivingVia extension is for, among other things.



          -# language DerivingVia #-

          newtype NP a = NP unNP::a

          instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
          parseJSON = fmap NP . genericParseJSON
          (defaultOptions fieldLabelModifier = body_noprefix )

          instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
          toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


          Now, you can write



          deriving via (NP User) instance FromJSON User


          Or



          data User = ...
          deriving Generic
          deriving (FromJSON, ToJSON) via (NP User)


          and so on.



          This doesn't save a lot over leftaroundabout's answer as it is. However, once you add a definition of toEncoding, it starts to look worthwhile.



          Caution: I have tested none of this.






          share|improve this answer

























          • I see this as the most elegant solution until now. There is just a small typo here: ToJSON = should be toJSON =.

            – fata
            Mar 21 at 15:50
















          3














          This is what the fairly new DerivingVia extension is for, among other things.



          -# language DerivingVia #-

          newtype NP a = NP unNP::a

          instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
          parseJSON = fmap NP . genericParseJSON
          (defaultOptions fieldLabelModifier = body_noprefix )

          instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
          toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


          Now, you can write



          deriving via (NP User) instance FromJSON User


          Or



          data User = ...
          deriving Generic
          deriving (FromJSON, ToJSON) via (NP User)


          and so on.



          This doesn't save a lot over leftaroundabout's answer as it is. However, once you add a definition of toEncoding, it starts to look worthwhile.



          Caution: I have tested none of this.






          share|improve this answer

























          • I see this as the most elegant solution until now. There is just a small typo here: ToJSON = should be toJSON =.

            – fata
            Mar 21 at 15:50














          3












          3








          3







          This is what the fairly new DerivingVia extension is for, among other things.



          -# language DerivingVia #-

          newtype NP a = NP unNP::a

          instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
          parseJSON = fmap NP . genericParseJSON
          (defaultOptions fieldLabelModifier = body_noprefix )

          instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
          toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


          Now, you can write



          deriving via (NP User) instance FromJSON User


          Or



          data User = ...
          deriving Generic
          deriving (FromJSON, ToJSON) via (NP User)


          and so on.



          This doesn't save a lot over leftaroundabout's answer as it is. However, once you add a definition of toEncoding, it starts to look worthwhile.



          Caution: I have tested none of this.






          share|improve this answer















          This is what the fairly new DerivingVia extension is for, among other things.



          -# language DerivingVia #-

          newtype NP a = NP unNP::a

          instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
          parseJSON = fmap NP . genericParseJSON
          (defaultOptions fieldLabelModifier = body_noprefix )

          instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
          toJSON = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix ) . unNP


          Now, you can write



          deriving via (NP User) instance FromJSON User


          Or



          data User = ...
          deriving Generic
          deriving (FromJSON, ToJSON) via (NP User)


          and so on.



          This doesn't save a lot over leftaroundabout's answer as it is. However, once you add a definition of toEncoding, it starts to look worthwhile.



          Caution: I have tested none of this.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 22 at 3:41

























          answered Mar 21 at 2:14









          dfeuerdfeuer

          33.8k349133




          33.8k349133












          • I see this as the most elegant solution until now. There is just a small typo here: ToJSON = should be toJSON =.

            – fata
            Mar 21 at 15:50


















          • I see this as the most elegant solution until now. There is just a small typo here: ToJSON = should be toJSON =.

            – fata
            Mar 21 at 15:50

















          I see this as the most elegant solution until now. There is just a small typo here: ToJSON = should be toJSON =.

          – fata
          Mar 21 at 15:50






          I see this as the most elegant solution until now. There is just a small typo here: ToJSON = should be toJSON =.

          – fata
          Mar 21 at 15:50














          2














          Like,



          noPrefixParseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
          noPrefixParseJSON
          = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
          noPrefixToJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value
          noPrefixToJSON
          = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

          instance FromJSON User where parseJSON = noPrefixParseJSON
          instance ToJSON User where toJSON = noPrefixToJSON
          instance FromJSON Role where parseJSON = noPrefixParseJSON
          instance ToJSON Role where toJSON = noPrefixToJSON
          ...


          Sure this is still kind of repetitive, but I'd say this isn't any cause of worry any more.






          share|improve this answer

























          • It's a good idea to extract the function definitions but the main problem still remains in my opinion. Maybe a meta programming solution via template haskell is the correct way to go?

            – fata
            Mar 20 at 20:59















          2














          Like,



          noPrefixParseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
          noPrefixParseJSON
          = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
          noPrefixToJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value
          noPrefixToJSON
          = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

          instance FromJSON User where parseJSON = noPrefixParseJSON
          instance ToJSON User where toJSON = noPrefixToJSON
          instance FromJSON Role where parseJSON = noPrefixParseJSON
          instance ToJSON Role where toJSON = noPrefixToJSON
          ...


          Sure this is still kind of repetitive, but I'd say this isn't any cause of worry any more.






          share|improve this answer

























          • It's a good idea to extract the function definitions but the main problem still remains in my opinion. Maybe a meta programming solution via template haskell is the correct way to go?

            – fata
            Mar 20 at 20:59













          2












          2








          2







          Like,



          noPrefixParseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
          noPrefixParseJSON
          = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
          noPrefixToJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value
          noPrefixToJSON
          = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

          instance FromJSON User where parseJSON = noPrefixParseJSON
          instance ToJSON User where toJSON = noPrefixToJSON
          instance FromJSON Role where parseJSON = noPrefixParseJSON
          instance ToJSON Role where toJSON = noPrefixToJSON
          ...


          Sure this is still kind of repetitive, but I'd say this isn't any cause of worry any more.






          share|improve this answer















          Like,



          noPrefixParseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
          noPrefixParseJSON
          = genericParseJSON (defaultOptions fieldLabelModifier = body_noprefix )
          noPrefixToJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value
          noPrefixToJSON
          = genericToJSON (defaultOptions fieldLabelModifier = body_noprefix )

          instance FromJSON User where parseJSON = noPrefixParseJSON
          instance ToJSON User where toJSON = noPrefixToJSON
          instance FromJSON Role where parseJSON = noPrefixParseJSON
          instance ToJSON Role where toJSON = noPrefixToJSON
          ...


          Sure this is still kind of repetitive, but I'd say this isn't any cause of worry any more.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 21 at 22:38









          dfeuer

          33.8k349133




          33.8k349133










          answered Mar 20 at 19:38









          leftaroundaboutleftaroundabout

          80.6k3121240




          80.6k3121240












          • It's a good idea to extract the function definitions but the main problem still remains in my opinion. Maybe a meta programming solution via template haskell is the correct way to go?

            – fata
            Mar 20 at 20:59

















          • It's a good idea to extract the function definitions but the main problem still remains in my opinion. Maybe a meta programming solution via template haskell is the correct way to go?

            – fata
            Mar 20 at 20:59
















          It's a good idea to extract the function definitions but the main problem still remains in my opinion. Maybe a meta programming solution via template haskell is the correct way to go?

          – fata
          Mar 20 at 20:59





          It's a good idea to extract the function definitions but the main problem still remains in my opinion. Maybe a meta programming solution via template haskell is the correct way to go?

          – fata
          Mar 20 at 20:59











          0














          If explicitly declaring all those similar instances proves too onerous, perhaps you could parameterize your datatypes with a phantom type like



          data User x = User aa :: Int, bb :: Bool deriving Generic

          data Role x = Role xx :: Int, dd :: Bool deriving Generic


          and then define a "marker" datatype like



          data Marker


          This datatype will only serve as a peg on which to hang instances like the following



          -# language UndecidableInstances #-
          instance (Generic (f Marker), GFromJSON Zero (Rep (f Marker))) => FromJSON (f Marker) where
          parseJSON = noPrefixParseJSON


          Would it be worth it? Likely not, because the definition of your datatypes becomes more complex. On the other hand, you could change aspects of the serialization by varying the marker, so you gain some flexibility.






          share|improve this answer

























          • That instance overlaps a lot. I think a newtype taking a phantom marker (or even a list of markers) would be a lot cleaner. That could also be useful for the DerivingVia approach I outlined in my answer, if you want to do a lot of type-level work up front.

            – dfeuer
            Mar 22 at 1:51











          • @dfeuer I believe it overlaps with more concrete types also parametrized with Marker, but the idea is that Marker will be used only with entities defined in the same module, and for those we wanted "uniform" instances anyway. A problem I see with the newtype is that if Role is nested within User, we also have to put the newtype there, which seems inconvenient.

            – danidiaz
            Mar 22 at 7:24












          • I'm pretty sure it will also affect instance resolution in some other circumstances. For example, suppose you want the instance for Const Int a, where a is neither specified nor inferred. Having your instance in scope will cause resolution to fail where it would otherwise succeed, because the compiler now wants to know that a is not the marker type.

            – dfeuer
            Mar 22 at 7:56











          • @dfeuer The GHC User Guide states that "It is fine for there to be a potential of overlap […] an error is only reported if a particular constraint matches more than one [instance]" downloads.haskell.org/~ghc/latest/docs/html/users_guide/… So, as long as we don't require FromJSON from a Const Int Marker in our program, we won't get any overlapping instances error.

            – danidiaz
            Mar 22 at 18:30











          • Huh .... It looks like I was overly optimistic about resolution without that instance. I'm pretty sure I've encountered situations where that hurt when messing around with Data.Constraint.Forall; I'll have to dig a bit further and see if I can produce a real example.

            – dfeuer
            Mar 22 at 20:09















          0














          If explicitly declaring all those similar instances proves too onerous, perhaps you could parameterize your datatypes with a phantom type like



          data User x = User aa :: Int, bb :: Bool deriving Generic

          data Role x = Role xx :: Int, dd :: Bool deriving Generic


          and then define a "marker" datatype like



          data Marker


          This datatype will only serve as a peg on which to hang instances like the following



          -# language UndecidableInstances #-
          instance (Generic (f Marker), GFromJSON Zero (Rep (f Marker))) => FromJSON (f Marker) where
          parseJSON = noPrefixParseJSON


          Would it be worth it? Likely not, because the definition of your datatypes becomes more complex. On the other hand, you could change aspects of the serialization by varying the marker, so you gain some flexibility.






          share|improve this answer

























          • That instance overlaps a lot. I think a newtype taking a phantom marker (or even a list of markers) would be a lot cleaner. That could also be useful for the DerivingVia approach I outlined in my answer, if you want to do a lot of type-level work up front.

            – dfeuer
            Mar 22 at 1:51











          • @dfeuer I believe it overlaps with more concrete types also parametrized with Marker, but the idea is that Marker will be used only with entities defined in the same module, and for those we wanted "uniform" instances anyway. A problem I see with the newtype is that if Role is nested within User, we also have to put the newtype there, which seems inconvenient.

            – danidiaz
            Mar 22 at 7:24












          • I'm pretty sure it will also affect instance resolution in some other circumstances. For example, suppose you want the instance for Const Int a, where a is neither specified nor inferred. Having your instance in scope will cause resolution to fail where it would otherwise succeed, because the compiler now wants to know that a is not the marker type.

            – dfeuer
            Mar 22 at 7:56











          • @dfeuer The GHC User Guide states that "It is fine for there to be a potential of overlap […] an error is only reported if a particular constraint matches more than one [instance]" downloads.haskell.org/~ghc/latest/docs/html/users_guide/… So, as long as we don't require FromJSON from a Const Int Marker in our program, we won't get any overlapping instances error.

            – danidiaz
            Mar 22 at 18:30











          • Huh .... It looks like I was overly optimistic about resolution without that instance. I'm pretty sure I've encountered situations where that hurt when messing around with Data.Constraint.Forall; I'll have to dig a bit further and see if I can produce a real example.

            – dfeuer
            Mar 22 at 20:09













          0












          0








          0







          If explicitly declaring all those similar instances proves too onerous, perhaps you could parameterize your datatypes with a phantom type like



          data User x = User aa :: Int, bb :: Bool deriving Generic

          data Role x = Role xx :: Int, dd :: Bool deriving Generic


          and then define a "marker" datatype like



          data Marker


          This datatype will only serve as a peg on which to hang instances like the following



          -# language UndecidableInstances #-
          instance (Generic (f Marker), GFromJSON Zero (Rep (f Marker))) => FromJSON (f Marker) where
          parseJSON = noPrefixParseJSON


          Would it be worth it? Likely not, because the definition of your datatypes becomes more complex. On the other hand, you could change aspects of the serialization by varying the marker, so you gain some flexibility.






          share|improve this answer















          If explicitly declaring all those similar instances proves too onerous, perhaps you could parameterize your datatypes with a phantom type like



          data User x = User aa :: Int, bb :: Bool deriving Generic

          data Role x = Role xx :: Int, dd :: Bool deriving Generic


          and then define a "marker" datatype like



          data Marker


          This datatype will only serve as a peg on which to hang instances like the following



          -# language UndecidableInstances #-
          instance (Generic (f Marker), GFromJSON Zero (Rep (f Marker))) => FromJSON (f Marker) where
          parseJSON = noPrefixParseJSON


          Would it be worth it? Likely not, because the definition of your datatypes becomes more complex. On the other hand, you could change aspects of the serialization by varying the marker, so you gain some flexibility.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 21 at 0:14

























          answered Mar 20 at 22:13









          danidiazdanidiaz

          17.5k33058




          17.5k33058












          • That instance overlaps a lot. I think a newtype taking a phantom marker (or even a list of markers) would be a lot cleaner. That could also be useful for the DerivingVia approach I outlined in my answer, if you want to do a lot of type-level work up front.

            – dfeuer
            Mar 22 at 1:51











          • @dfeuer I believe it overlaps with more concrete types also parametrized with Marker, but the idea is that Marker will be used only with entities defined in the same module, and for those we wanted "uniform" instances anyway. A problem I see with the newtype is that if Role is nested within User, we also have to put the newtype there, which seems inconvenient.

            – danidiaz
            Mar 22 at 7:24












          • I'm pretty sure it will also affect instance resolution in some other circumstances. For example, suppose you want the instance for Const Int a, where a is neither specified nor inferred. Having your instance in scope will cause resolution to fail where it would otherwise succeed, because the compiler now wants to know that a is not the marker type.

            – dfeuer
            Mar 22 at 7:56











          • @dfeuer The GHC User Guide states that "It is fine for there to be a potential of overlap […] an error is only reported if a particular constraint matches more than one [instance]" downloads.haskell.org/~ghc/latest/docs/html/users_guide/… So, as long as we don't require FromJSON from a Const Int Marker in our program, we won't get any overlapping instances error.

            – danidiaz
            Mar 22 at 18:30











          • Huh .... It looks like I was overly optimistic about resolution without that instance. I'm pretty sure I've encountered situations where that hurt when messing around with Data.Constraint.Forall; I'll have to dig a bit further and see if I can produce a real example.

            – dfeuer
            Mar 22 at 20:09

















          • That instance overlaps a lot. I think a newtype taking a phantom marker (or even a list of markers) would be a lot cleaner. That could also be useful for the DerivingVia approach I outlined in my answer, if you want to do a lot of type-level work up front.

            – dfeuer
            Mar 22 at 1:51











          • @dfeuer I believe it overlaps with more concrete types also parametrized with Marker, but the idea is that Marker will be used only with entities defined in the same module, and for those we wanted "uniform" instances anyway. A problem I see with the newtype is that if Role is nested within User, we also have to put the newtype there, which seems inconvenient.

            – danidiaz
            Mar 22 at 7:24












          • I'm pretty sure it will also affect instance resolution in some other circumstances. For example, suppose you want the instance for Const Int a, where a is neither specified nor inferred. Having your instance in scope will cause resolution to fail where it would otherwise succeed, because the compiler now wants to know that a is not the marker type.

            – dfeuer
            Mar 22 at 7:56











          • @dfeuer The GHC User Guide states that "It is fine for there to be a potential of overlap […] an error is only reported if a particular constraint matches more than one [instance]" downloads.haskell.org/~ghc/latest/docs/html/users_guide/… So, as long as we don't require FromJSON from a Const Int Marker in our program, we won't get any overlapping instances error.

            – danidiaz
            Mar 22 at 18:30











          • Huh .... It looks like I was overly optimistic about resolution without that instance. I'm pretty sure I've encountered situations where that hurt when messing around with Data.Constraint.Forall; I'll have to dig a bit further and see if I can produce a real example.

            – dfeuer
            Mar 22 at 20:09
















          That instance overlaps a lot. I think a newtype taking a phantom marker (or even a list of markers) would be a lot cleaner. That could also be useful for the DerivingVia approach I outlined in my answer, if you want to do a lot of type-level work up front.

          – dfeuer
          Mar 22 at 1:51





          That instance overlaps a lot. I think a newtype taking a phantom marker (or even a list of markers) would be a lot cleaner. That could also be useful for the DerivingVia approach I outlined in my answer, if you want to do a lot of type-level work up front.

          – dfeuer
          Mar 22 at 1:51













          @dfeuer I believe it overlaps with more concrete types also parametrized with Marker, but the idea is that Marker will be used only with entities defined in the same module, and for those we wanted "uniform" instances anyway. A problem I see with the newtype is that if Role is nested within User, we also have to put the newtype there, which seems inconvenient.

          – danidiaz
          Mar 22 at 7:24






          @dfeuer I believe it overlaps with more concrete types also parametrized with Marker, but the idea is that Marker will be used only with entities defined in the same module, and for those we wanted "uniform" instances anyway. A problem I see with the newtype is that if Role is nested within User, we also have to put the newtype there, which seems inconvenient.

          – danidiaz
          Mar 22 at 7:24














          I'm pretty sure it will also affect instance resolution in some other circumstances. For example, suppose you want the instance for Const Int a, where a is neither specified nor inferred. Having your instance in scope will cause resolution to fail where it would otherwise succeed, because the compiler now wants to know that a is not the marker type.

          – dfeuer
          Mar 22 at 7:56





          I'm pretty sure it will also affect instance resolution in some other circumstances. For example, suppose you want the instance for Const Int a, where a is neither specified nor inferred. Having your instance in scope will cause resolution to fail where it would otherwise succeed, because the compiler now wants to know that a is not the marker type.

          – dfeuer
          Mar 22 at 7:56













          @dfeuer The GHC User Guide states that "It is fine for there to be a potential of overlap […] an error is only reported if a particular constraint matches more than one [instance]" downloads.haskell.org/~ghc/latest/docs/html/users_guide/… So, as long as we don't require FromJSON from a Const Int Marker in our program, we won't get any overlapping instances error.

          – danidiaz
          Mar 22 at 18:30





          @dfeuer The GHC User Guide states that "It is fine for there to be a potential of overlap […] an error is only reported if a particular constraint matches more than one [instance]" downloads.haskell.org/~ghc/latest/docs/html/users_guide/… So, as long as we don't require FromJSON from a Const Int Marker in our program, we won't get any overlapping instances error.

          – danidiaz
          Mar 22 at 18:30













          Huh .... It looks like I was overly optimistic about resolution without that instance. I'm pretty sure I've encountered situations where that hurt when messing around with Data.Constraint.Forall; I'll have to dig a bit further and see if I can produce a real example.

          – dfeuer
          Mar 22 at 20:09





          Huh .... It looks like I was overly optimistic about resolution without that instance. I'm pretty sure I've encountered situations where that hurt when messing around with Data.Constraint.Forall; I'll have to dig a bit further and see if I can produce a real example.

          – dfeuer
          Mar 22 at 20:09

















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55268631%2favoiding-repeated-instance-declarations-in-haskell%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

          Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

          Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript