Opened 4 years ago

Last modified 12 days ago

#7492 new feature request

Generic1 deriving: Can we replace Rec1 f with f :.: Par1?

Reported by: spl Owned by: dreixel
Priority: normal Milestone:
Component: Compiler Version: 7.7
Keywords: Generics Cc: spl
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

It seems like Rec1 f is isomorphic to f :.: Par1. Is it possible and beneficial to replace the former with the latter and deprecate/remove Rec1?

  1. Currently, a parameter type is found in Par1 or Rec1. By removing Rec1, there would be only one place for parameters. This simplifies generic functions.
  2. It is in the interest of reducing redundancy in the representation, something that appears to be consistent with the design of the representation types (e.g. using the same type for multiple meanings).

Change History (11)

comment:1 Changed 4 years ago by simonpj

  • Cc changed from leather@cs.uu.nl to leather@cs.uu.nl,
  • difficulty set to Unknown
  • Owner set to dreixel

comment:2 Changed 4 years ago by dreixel

You raise an interesting point, thanks. I think replacing Rec1 f with f :.: Par1 would be possible. But I'm not too keen on making a change to the representation right now, as I think there might be more fundamental changes coming up anyway (e.g. making use of DataKinds). But I'm leaving this open so that we don't forget the idea.

comment:3 Changed 3 years ago by igloo

  • Milestone set to 7.8.1

comment:4 Changed 2 years ago by thoughtpolice

  • Cc changed from leather@cs.uu.nl, to leather@cs.uu.nl
  • Milestone changed from 7.8.3 to 7.10.1

Moving to 7.10.1

comment:5 Changed 20 months ago by thoughtpolice

  • Milestone changed from 7.10.1 to 7.12.1

Moving to 7.12.1 milestone; if you feel this is an error and should be addressed sooner, please move it back to the 7.10.1 milestone.

comment:6 Changed 12 months ago by thoughtpolice

  • Milestone changed from 7.12.1 to 8.0.1

Milestone renamed

comment:7 Changed 9 months ago by RyanGlScott

The changes Pedro was alluding to involving DataKinds have now been implemented (#9766), so that's no longer holding this back. It would be interesting to talk about the pros and cons of changing Rec1 f to f :.: Par1

The obvious pro is that is removes a redundant representation type, making (:.:) the sole way to talk about type constructors being applied to the type parameter. I also suspect that this change would make #8516 easier, but that's a different story.

There are two cons that I can see:

  1. All code that declares instances for Rec1 would eventually have to be changed. We have a much better story for deprecation than we used to, though, so this isn't a dealbreaker.
  1. Generic1 instances involving Rec1 have different instance heads than instances involving (:.:). To be more specific, consider this data type:
newtype T1 a = T1 (T2 a) deriving Generic1

Right now, this would be derived Generic1 instance:

instance Generic1 T1 where
  type Rep1 T1 =
    D1 ('MetaData "T1" "Module" "package" 'True)
      (C1 ('MetaCons "T1" 'PrefixI 'False)
        (S1 'NoSelector (Rec1 T2)))
  from1 (T1 a) = M1 (M1 (M1 (Rec1 a)))
  to1 (M1 (M1 (M1 a))) = T1 (unRec1 a)

But with this proposal, it would be this:

instance Generic1 T1 where
  type Rep1 T1 =
    D1 ('MetaData "T1" "Module" "package" 'True)
      (C1 ('MetaCons "T1" 'PrefixI 'False)
        (S1 'NoSelector (T2 :.: Par1)))
  from1 (T1 a) = M1 (M1 (M1 (Comp1 (fmap Par1 a))))
  to1 (M1 (M1 (M1 a))) = T1 (fmap unPar1 (unComp1 a))

There's one very important difference here. The latter instance requires that T2 is a Functor instance, whereas the former instance does not! It would be interesting to know if this would prevent some datatypes in the wild from being Generic1 instances. For example, suppose newtype T2 a = T2 (a -> Int). Then we couldn't make T2 a Functor, and thus we couldn't make T1 Generic1!

comment:8 Changed 8 months ago by simonpj

  • Keywords Generics added

comment:9 Changed 7 months ago by thomie

  • Milestone 8.0.1 deleted

comment:10 Changed 13 days ago by RyanGlScott

This Functor issue might become less important in the future if we switch over to using a coercion-based approach to deriving Generic1. See https://ghc.haskell.org/trac/ghc/ticket/8516#comment:5 for more info.

comment:11 Changed 12 days ago by spl

  • Cc spl added; leather@… removed
Note: See TracTickets for help on using tickets.