[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 <ryan.gl.scott@…>): In [changeset:"132273f34e394bf7e900d0c15e01e91edd711890/ghc" 132273f3/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="132273f34e394bf7e900d0c15e01e91edd711890" Instantiate GND bindings with an explicit type signature Summary: Before, we were using visible type application to apply impredicative types to `coerce` in `GeneralizedNewtypeDeriving`-generated bindings. This approach breaks down when combined with `QuantifiedConstraints` in certain ways, which #14883 and #15290 provide examples of. See Note [GND and QuantifiedConstraints] for all the gory details. To avoid this issue, we instead use an explicit type signature to instantiate each GND binding, and use that to bind any type variables that might be bound by a class method's type signature. This reduces the need to impredicative type applications, and more importantly, makes the programs from #14883 and #15290 work again. Test Plan: make test TEST="T15290b T15290c T15290d T14883" Reviewers: simonpj, bgamari Reviewed By: simonpj Subscribers: rwbarton, thomie, carter GHC Trac Issues: #14883, #15290 Differential Revision: https://phabricator.haskell.org/D4895 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14883#comment:10> 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: 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