Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1. Implement SOP.Generic (GHC.Generically a) and 2. export SOP.Generically #153

Open
Icelandjack opened this issue Mar 17, 2022 · 8 comments

Comments

@Icelandjack
Copy link

Icelandjack commented Mar 17, 2022

Here are 2 suggestions once we get GHC.Generically and GHC.Generically1 in base 4.17.

Those are simply newtypes, if you have a definition in terms of GHC.Generic or GHC.Generic1 then you give it an instance.

-- GHC.Generics
newtype Generically    a = Generically  a
newtype Generically1 f a = Generically1 (f a)
  1. SOP.Generic has an implementation in terms of GHC.Generic, thus I propose the following instance:

    instance (GHC.Generic a, GFrom a, GTo a, Rep a ~ SOP I (GCode a))
          => SOP.Generic (GHC.Generically a) where
      type Code (GHC.Generically a) = GCode a
      from = gfrom
      to   = gto

    This way an instance of SOP.Generic T can be derived: deriving SOP.Generic via GHC.Generically T.

  2. I also propose defining a newtype with the same name as Generically, to be imported qualified with SOP.Generically, it will serve the same purpose but for SOP.Generic definitions. I think every data-type generic library should export a name like that. If I can implement Binary in terms of SOP.Generic I define instance (SOP.Generic a, ..) => Binary (SOP.Generically a):

    -- Generics.SOP
    newtype Generically a = Generically a

A newtype like SOP.Generically can be combined with a library like generic-override that overrides the generic representation of an instance, so we decouple a generic implementation from modifying the generic implementation:

data X = X { s :: Int, p :: Int }
 deriving stock GHC.Generic
 
 -- 1.
 deriving SOP.Generic via GHC.Generically X
 
 -- 2. 
 deriving (Semigroup, Monoid) via SOP.Generically
   (Override X
     '[ "x" `As` Sum Int
      , "y" `As` Product Int
      ])
@kosmikus
Copy link
Member

Thanks! In principle, I'm in support of both, although regarding part 2, I'm somewhat afraid that the presence of the type will go mostly unnoticed, because the library itself has hardly any generic functions, so it would basically be a type without instances.

@Icelandjack
Copy link
Author

Icelandjack commented Apr 20, 2022

For 1. I think this pragma should work

#if MIN_VERSION_base(4,17,0)
#define HAS_GENERICALLY
#endif

And then this is a backwards compatible definition for GHC.Generically

#ifdef HAS_GENERICALLY
instance .. => SOP.Generic (GHC.Generically a) where
  .. 
#endif

For 2. I share the concern, I was thinking that it would mostly be up to other libraries that depend on generics-sop to specify instances without having to depend on another library. generics-sop can add instances for the base classes with time.

Maybe it belongs in basic-sop instead? It already has a generics-sop Eq instance, but there I feel like it would go unnoticed as well.

@Icelandjack
Copy link
Author

Icelandjack commented Nov 17, 2022

For 1. you can use the generically compatibility package.

I think Generically¹ should be defined so people can start attaching instances to it, I would expect that if I have the generics-sop package that I can define generic instances. It just depends if you mind defining orphan instances in basic-sop.

¹ What name should be chosen? SOPGenerically? At first I thought of qualified Generically: SOP.Generically but I don't like the idea of dealing with the clash.

import Generics.SOP hiding (Generically(..))
import qualified Generics.SOP as SOP (Generically)

@phadej
Copy link
Contributor

phadej commented Nov 17, 2022

There is already a name clash in Generic type-class name.

@Icelandjack
Copy link
Author

So you're fine with exporting this as Generically?

@phadej
Copy link
Contributor

phadej commented Nov 17, 2022

So you're fine with exporting this as Generically?

It's up to @kosmikus

@kosmikus
Copy link
Member

Yes, as long as we don't rename the Generic class, I don't see an issue with calling the newtype Generically as well.

@Icelandjack do you want to submit a PR? Otherwise, I'll try to do this whenever I next get around to making changes on the library.

@Icelandjack
Copy link
Author

I made a PR #159 and updated some of the documentation. I didn't build the project so there may be some errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants