Opened 4 years ago

Closed 4 years ago

Last modified 3 years ago

#10775 closed feature request (fixed)

Enable PolyKinds in GHC.Generics

Reported by: RyanGlScott Owned by: RyanGlScott
Priority: normal Milestone: 8.0.1
Component: libraries/base Version: 7.10.2
Keywords: Generics Cc: dreixel
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: #10604 Differential Rev(s): Phab:D1166
Wiki Page:

Description

As suggested in this Haskell libraries mailing list thread. Among other benefits, this would allow use of generic functions with Proxy t when t is of a kind other than *.

There seem to be more changes required than just putting {-# LANGUAGE PolyKinds #-} in GHC.Generics, however, since I tried doing that myself and found myself unable to properly derive Generic(1) instances in GHC.Generics. Here is a snippet of the resulting error message:

libraries/base/GHC/Generics.hs:826:1: error:
    Couldn't match type ‘M1 i0 c0 (M1 i1 c1 U1) p0’ with ‘M1 D x’
    Expected type: Rep (Proxy t) x
      Actual type: M1 i0 c0 (M1 i1 c1 U1) p0
    Relevant bindings include
      from :: Proxy t -> Rep (Proxy t) x
        (bound at libraries/base/GHC/Generics.hs:826:1)
    In the expression: M1 (M1 U1)
    In an equation for ‘from’: from Proxy = M1 (M1 U1)
    When typechecking the code for ‘from’
      in a derived instance for ‘Generic (Proxy t)’:
      To see the code I am typechecking, use -ddump-deriv

libraries/base/GHC/Generics.hs:826:1: error:
    Couldn't match type ‘M1 t0 t1 (M1 t3 t4 U1) t2’ with ‘M1 D x’
    Expected type: Rep (Proxy t) x
      Actual type: M1 t0 t1 (M1 t3 t4 U1) t2
    Relevant bindings include
      to :: Rep (Proxy t) x -> Proxy t
        (bound at libraries/base/GHC/Generics.hs:826:1)
    In the pattern: M1 (M1 U1)
    In an equation for ‘to’: to (M1 (M1 U1)) = Proxy
    When typechecking the code for ‘to’
      in a derived instance for ‘Generic (Proxy t)’:
      To see the code I am typechecking, use -ddump-deriv
    In the instance declaration for ‘Generic (Proxy t)’

Change History (13)

comment:1 Changed 4 years ago by dreixel

I'm not entirely sure what's the goal here. To make Generic1 :: k -> * instead of its current Generic1 :: * -> * kind?

comment:2 Changed 4 years ago by RyanGlScott

To make Generic1 :: k -> * instead of its current Generic1 :: * -> * kind?

No, my main motivation involves Proxy from Data.Proxy. Currently, Proxy is defined like so:

data Proxy (t :: k) = Proxy

using PolyKinds, but Proxy has a Generic instance defined in GHC.Generics, a module which doesn't have PolyKinds enabled. As a result, the resulting Generic instance is

instance Generic (Proxy (t :: *))

This prevents you from using certain Proxy values with generic functions:

$ ghci -XPolyKinds
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
λ> import GHC.Generics
λ> import Data.Proxy
λ> from (Proxy :: Proxy Int)
M1 {unM1 = M1 {unM1 = U1}}
λ> from (Proxy :: Proxy Maybe)

<interactive>:5:1:
    No instance for (Generic (Proxy Maybe))
      (maybe you haven't applied enough arguments to a function?)
      arising from a use of ‘from’
    In the expression: from (Proxy :: Proxy Maybe)
    In an equation for ‘it’: it = from (Proxy :: Proxy Maybe)

If GHC.Generics enabled PolyKinds, that would fix this issue. It would also make many data types in GHC.Generics poly-kinded as well, as an added bonus.

(I had originally thought Generic1/Rep1 could be poly-kinded, but upon further thought, I think the current GHC generics mechanism assumes that the last type parameter is always of kind * -> *.)

comment:3 Changed 4 years ago by bgamari

Do you happen to have the output from -ddump-deriv available? I'm having a bit of difficulty seeing why this should just work (although I may be missing something obvious).

comment:4 Changed 4 years ago by dreixel

I think what you're after is a very small subset of the changes to GHC.Generics.hs here: https://phabricator.haskell.org/D493?vs=on&id=1690&whitespace=ignore-most#15796e19

Probably just adding the :: * kind signatures in the definitions of the representation types, I think.

comment:5 Changed 4 years ago by RyanGlScott

bgamari: The output of -ddump-deriv is extremely long, but here are the parts pertaining to Proxy:

==================== Derived instances ====================
Derived instances:
  instance forall (k_a21F :: BOX) (t_a21G :: k_a21F).
           GHC.Generics.Generic (Data.Proxy.Proxy t_a21G) where
    GHC.Generics.from Data.Proxy.Proxy
      = GHC.Generics.M1 (GHC.Generics.M1 GHC.Generics.U1)
    GHC.Generics.to (GHC.Generics.M1 (GHC.Generics.M1 GHC.Generics.U1))
      = Data.Proxy.Proxy

  instance GHC.Generics.Datatype where
    GHC.Generics.datatypeName _ = "Proxy"
    GHC.Generics.moduleName _ = "Data.Proxy"
    GHC.Generics.packageName _ = "base"

  instance GHC.Generics.Constructor where
    GHC.Generics.conName _ = "Proxy"

Generic representation:
  
  Generated datatypes for meta-information:
    GHC.Generics.D1Proxy
    GHC.Generics.C1_0Proxy

  Representation types:
    type GHC.Generics.Rep (Data.Proxy.Proxy t_a21E) = GHC.Generics.D1

That definitely doesn't look right, especially since it should be that Rep (Proxy t) = D1 D1Proxy (C1 C1_0Proxy U1).

Luckily, this may be a moot issue. I wasn't aware of Phab:D493, which happens to enable PolyKinds in GHC.Generics as a happy coincidence. Therefore, this is probably subsumed by #9766.

Last edited 4 years ago by RyanGlScott (previous) (diff)

comment:6 Changed 4 years ago by RyanGlScott

Blocked By: 9766 added

comment:7 Changed 4 years ago by dreixel

Blocked By: 9766 removed

This doesn't need to depend on #9766. This is a small change that can be done on its own. Go for it, I'd say :-)

comment:8 Changed 4 years ago by RyanGlScott

Differential Rev(s): Phab:D1166
Owner: set to RyanGlScott

comment:9 Changed 4 years ago by Ben Gamari <ben@…>

In a6826c5/ghc:

Make Generic (Proxy t) instance poly-kinded (fixes #10775)

This amounts to enabling PolyKinds in GHC.Generics. However, explicit
kind signatures must be applied to the datatypes and typeclasses in
GHC.Generics to ensure that the Core which TcGenGenerics generates
is properly kinded.

Several of the typeclasses in GHC.Generics could be poly-kinded, but
this differential does not attempt to address this, since D493 already
addresses this.

Test Plan: ./validate

Reviewers: hvr, austin, dreixel, bgamari

Reviewed By: austin, dreixel, bgamari

Subscribers: goldfire, thomie

Differential Revision: https://phabricator.haskell.org/D1166

GHC Trac Issues: #10775

comment:10 Changed 4 years ago by bgamari

Resolution: fixed
Status: newclosed

Merged.

comment:11 Changed 4 years ago by thomie

Milestone: 8.0.1

comment:12 Changed 4 years ago by RyanGlScott

Keywords: Generics added

comment:13 Changed 3 years ago by RyanGlScott

See also #10604, which concerns making the definition of Generic1 itself leverage PolyKinds.

Note: See TracTickets for help on using tickets.