Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,250
    • Issues 5,250
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 583
    • Merge requests 583
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #19906
Closed
Open
Issue created May 27, 2021 by Icelandjack@IcelandjackReporter

Should Generically (/ Generically1) derive newtype Generic (/ Generic1)?

Regarding #17147 (!5726 (closed)), this may be controversial and touch on the philosophy of Generic. "Generic" is universally derived using the stock deriving strategy. I propose deriving those instances for Generically{,1} using generalized newtype deriving, by reusing the underlying Generic{,1} instances. This is in line with all other instances for Generically{,1} as they are defined using the generic representation of the underlying type.

type    Generically :: Type -> Type
newtype Generically a = Generically a
  deriving
  newtype Generic

type    Generically1 :: (k -> Type) -> k -> Type
newtype Generically1 f a = Generically1 (f a)
  deriving
  newtype Generic1

That is to say be given the following instance

instance Generic a => Generic (Generically a) where
 type Rep (Generically a) = Rep a

 from :: Generically a -> Rep a b
 from (Generically a) = from a

 to :: Rep a b -> Generically a
 to = Generically . to

instance Generic1 f => Generic1 (Generically1 f) where
 type Rep1 (Generically1 f) = Rep1 f

 from1 :: Generically1 f a -> Rep1 f a
 from1 (Generically1 as) = from1 as

 to1 :: Rep1 f a -> Generically1 f a
 to1 = Generically1 . to1

The other instances avoid newtype wrapping

  Generically a <> Generically b = Generically (to (from a <> from b :: Rep a ()))
  mempty = Generically (to (mempty :: Rep a ()))

  fmap f (Generically1 as) = Generically1 (to1 (fmap f (from1 as)))
  a <$ Generically1 as = Generically1 (to1 (a <$ from1 as))
  pure a = Generically1 (to1 (pure a))
  Generically1 fs <*> Generically1 as = Generically1 (to1 (from1 fs <*> from1 as))
  liftA2 (·) (Generically1 as) (Generically1 bs) = Generically1 (to1 (liftA2 (·) (from1 as) (from1 bs)))
  empty = Generically1 (to1 empty)
  Generically1 as1 <|> Generically1 as2 = Generically1 (to1 (from1 as1 <|> from1 as2))

--->

  a <> b = to (from a <> from b :: Rep a ())
  mempty = to (mempty :: Rep a ())

  fmap f = to1 . fmap f . from1 
  a <$ as = to1 (a <$ from1 as)
  pure = to1 . pure
  fs <*> as = to1 (from1 fs <*> from1 as)
  liftA2 (·) as bs = to1 (liftA2 (·) (from1 as) (from1 bs))
  empty = to1 empty
  as1 <|> as2 = to1 (from1 as1 <|> from1 as2)
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking