Re: [GHC] #7492: Generic1 deriving: Can we replace Rec1 f with f :.: Par1?

#7492: Generic1 deriving: Can we replace Rec1 f with f :.: Par1? -------------------------------------+------------------------------------- Reporter: spl | Owner: dreixel Type: feature request | Status: new Priority: normal | Milestone: 8.0.1 Component: Compiler | Version: 7.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (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. 2. `Generic1` instances involving `Rec1` have different instance heads than instances involving `(:.:)`. To be more specific, consider this data type: {{{#!hs newtype T1 a = T1 (T2 a) deriving Generic1 }}} Right now, this would be derived `Generic1` instance: {{{#!hs 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: {{{#!hs 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`! -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/7492#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC