[GHC] #14883: QuantifiedConstraints don't kick in when used in TypeApplications

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.5 (Type checker) | Keywords: | Operating System: Unknown/Multiple QuantifiedConstraints, wipT2893 | Architecture: | Type of failure: GHC rejects Unknown/Multiple | valid program Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider the following program: {{{#!hs {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE ImpredicativeTypes #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} module Bug where import Data.Coerce import Data.Kind type Representational1 m = (forall a b. Coercible a b => Coercible (m a) (m b) :: Constraint) class Representational1 f => Functor' f where fmap' :: (a -> b) -> f a -> f b class Functor' f => Applicative' f where pure' :: a -> f a (<*>@) :: f (a -> b) -> f a -> f b class Functor' t => Traversable' t where traverse' :: Applicative' f => (a -> f b) -> t a -> f (t b) -- Typechecks newtype T1 m a = MkT1 (m a) deriving Functor' instance Traversable' m => Traversable' (T1 m) where traverse' :: forall f a b. (Applicative' f) => (a -> f b) -> T1 m a -> f (T1 m b) traverse' = coerce @((a -> f b) -> m a -> f (m b)) @((a -> f b) -> T1 m a -> f (T1 m b)) traverse' -- Doesn't typecheck newtype T2 m a = MkT2 (m a) deriving Functor' instance Traversable' m => Traversable' (T2 m) where traverse' = coerce @(forall f a b. Applicative' f => (a -> f b) -> m a -> f (m b)) @(forall f a b. Applicative' f => (a -> f b) -> T2 m a -> f (T2 m b)) traverse' }}} This defines a variant of `Functor` that has `forall a b. Coercible a b. Coercible (m a) (m b)` as a superclass, and also defines versions of `Applicative` and `Traversable` that use this `Functor` variant. This is towards the ultimate goal of defining `Traversable'` à la `GeneralizedNewtypeDeriving`. This attempt (using `InstanceSigs`) typechecks: {{{#!hs newtype T1 m a = MkT1 (m a) deriving Functor' instance Traversable' m => Traversable' (T1 m) where traverse' :: forall f a b. (Applicative' f) => (a -> f b) -> T1 m a -> f (T1 m b) traverse' = coerce @((a -> f b) -> m a -> f (m b)) @((a -> f b) -> T1 m a -> f (T1 m b)) traverse' }}} However, this version (which is closer to what `GeneralizedNewtypeDeriving` would actually create) does //not// typecheck: {{{#!hs newtype T2 m a = MkT2 (m a) deriving Functor' instance Traversable' m => Traversable' (T2 m) where traverse' = coerce @(forall f a b. Applicative' f => (a -> f b) -> m a -> f (m b)) @(forall f a b. Applicative' f => (a -> f b) -> T2 m a -> f (T2 m b)) traverse' }}} {{{ $ ghc-cq/inplace/bin/ghc-stage2 --interactive Bug.hs GHCi, version 8.5.20180128: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/rgscott/.ghci [1 of 1] Compiling Bug ( Bug.hs, interpreted ) Bug.hs:38:15: error: • Couldn't match representation of type ‘f1 (m b1)’ with that of ‘f1 (T2 m b1)’ arising from a use of ‘coerce’ NB: We cannot know what roles the parameters to ‘f1’ have; we must assume that the role is nominal • In the expression: coerce @(forall f a b. Applicative' f => (a -> f b) -> m a -> f (m b)) @(forall f a b. Applicative' f => (a -> f b) -> T2 m a -> f (T2 m b)) traverse' In an equation for ‘traverse'’: traverse' = coerce @(forall f a b. Applicative' f => (a -> f b) -> m a -> f (m b)) @(forall f a b. Applicative' f => (a -> f b) -> T2 m a -> f (T2 m b)) traverse' In the instance declaration for ‘Traversable' (T2 m)’ • Relevant bindings include traverse' :: (a -> f b) -> T2 m a -> f (T2 m b) (bound at Bug.hs:38:3) | 38 | traverse' = coerce @(forall f a b. Applicative' f => (a -> f b) -> m a -> f (m b)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... }}} Shouldn't it, though? These instance declarations out to be equivalent (morally, at least). -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints, wipT2893 Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Another example in the same vein: {{{#!hs {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE ImpredicativeTypes #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} module Bug where import Data.Coerce import Data.Kind type Phantom1 p = (forall a b. Coercible (p a) (p b) :: Constraint) class Foo a where bar :: Phantom1 proxy => proxy a -> Int instance Foo Int where bar _ = 42 -- Typecheck newtype Age1 = MkAge1 Int instance Foo Age1 where bar :: forall proxy. Phantom1 proxy => proxy Age1 -> Int bar = coerce @(proxy Int -> Int) @(proxy Age1 -> Int) bar -- Doesn't typecheck newtype Age2 = MkAge2 Int instance Foo Age2 where bar = coerce @(forall proxy. Phantom1 proxy => proxy Int -> Int) @(forall proxy. Phantom1 proxy => proxy Age2 -> Int) bar }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints, wipT2893 Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Iceland_jack): * cc: Iceland_jack (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints, wipT2893 Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): Here's a simpler version of the original program, if `Traversable` is too dense: {{{#!hs {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE ImpredicativeTypes #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} module Bug where import Data.Coerce import Data.Kind type Representational1 m = (forall a b. Coercible a b => Coercible (m a) (m b) :: Constraint) class Distributive g where distribute :: Representational1 f => f (g a) -> g (f a) -- Typechecks newtype T1 g a = MkT1 (g a) instance Distributive g => Distributive (T1 g) where distribute :: forall f a. Representational1 f => f (T1 g a) -> T1 g (f a) distribute = coerce @(f (g a) -> g (f a)) @(f (T1 g a) -> T1 g (f a)) distribute -- Doesn't typecheck newtype T2 g a = MkT2 (g a) instance Distributive g => Distributive (T2 g) where distribute = coerce @(forall f a. Representational1 f => f (g a) -> g (f a)) @(forall f a. Representational1 f => f (T2 g a) -> T2 g (f a)) distribute }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * keywords: QuantifiedConstraints, wipT2893 => QuantifiedConstraints -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: 15290 | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * blockedby: => 15290 Comment: It turns out the original program now panics due to #15290, so that ticket is blocking this one. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: 15290 | Blocking: Related Tickets: #15290 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * related: => #15290 Comment: In light of https://ghc.haskell.org/trac/ghc/ticket/15290#comment:5, perhaps it's best that we not pursue making the impredicative variants typecheck. If we incorporate the change to `deriving` that Simon suggests in that ticket, then the code that would be generated for the original program would be: {{{#!hs instance Traversable' m => Traversable' (T1 m) where traverse' :: forall f a b. (Applicative' f) => (a -> f b) -> T1 m a -> f (T1 m b) traverse' = coerce @((a -> f b) -> m a -> f (m b)) traverse' }}} Which, conveniently enough, is pretty much exactly the `-- Typechecks` variant! So that's convenient. I'll keep this ticket open since as a reminder to check in these two lovely test cases, but implementing the `deriving` change in #15290 should make this whole issue moot. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: 15290 | Blocking: Related Tickets: #15290 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
implementing the deriving change in #15290 should make this whole issue moot.
Hurrah! -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: | QuantifiedConstraints Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: #15290 | Differential Rev(s): Phab:D4895 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: new => patch * differential: => Phab:D4895 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#14883: QuantifiedConstraints don't kick in when used in TypeApplications
-------------------------------------+-------------------------------------
Reporter: RyanGlScott | Owner: (none)
Type: bug | Status: patch
Priority: normal | Milestone:
Component: Compiler (Type | Version: 8.5
checker) | Keywords:
Resolution: | QuantifiedConstraints
Operating System: Unknown/Multiple | Architecture:
Type of failure: GHC rejects | Unknown/Multiple
valid program | Test Case:
Blocked By: | Blocking:
Related Tickets: #15290 | Differential Rev(s): Phab:D4895
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ryan Scott

#14883: QuantifiedConstraints don't kick in when used in TypeApplications -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: closed Priority: normal | Milestone: 8.6.1 Component: Compiler (Type | Version: 8.5 checker) | Keywords: Resolution: fixed | QuantifiedConstraints Operating System: Unknown/Multiple | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: #15290 | Differential Rev(s): Phab:D4895 Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * status: patch => closed * resolution: => fixed * milestone: => 8.6.1 Comment: As noted in comment:6, #15290 completely obviates the need for a setup like the `Traversable'` instance for `T2`, so this issue can be closed. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14883#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC