generics-sop icon indicating copy to clipboard operation
generics-sop copied to clipboard

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

Open Icelandjack opened this issue 3 years ago • 8 comments

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
      ])

Icelandjack avatar Mar 17 '22 22:03 Icelandjack

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.

kosmikus avatar Apr 19 '22 12:04 kosmikus

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 avatar Apr 20 '22 15:04 Icelandjack

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)

Icelandjack avatar Nov 17 '22 17:11 Icelandjack

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

phadej avatar Nov 17 '22 18:11 phadej

So you're fine with exporting this as Generically?

Icelandjack avatar Nov 17 '22 18:11 Icelandjack

So you're fine with exporting this as Generically?

It's up to @kosmikus

phadej avatar Nov 17 '22 18:11 phadej

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.

kosmikus avatar Nov 24 '22 12:11 kosmikus

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

Icelandjack avatar Nov 24 '22 17:11 Icelandjack