[GHC] #7492: Generic1 deriving: Can we replace Rec1 f with f :.: Par1?
GHC
ghc-devs at haskell.org
Mon Dec 7 17:49:12 UTC 2015
#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
More information about the ghc-tickets
mailing list