Skip to content

(forall x. c x, forall x. d x) is not equivalent to forall x. (c x, d x)

Consider the following code:

{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Foo where

import Data.Kind

type family F a :: Type -> Type
newtype WrappedF a b = WrapF (F a b)
deriving instance Functor (F a) => Functor (WrappedF a)
deriving instance Foldable (F a) => Foldable (WrappedF a)
deriving instance Traversable (F a) => Traversable (WrappedF a)

data SomeF b = forall a. MkSomeF (WrappedF a b)

deriving instance (forall a. Functor (WrappedF a))  => Functor SomeF
deriving instance (forall a. Foldable (WrappedF a)) => Foldable SomeF
deriving instance ( forall a. Functor (WrappedF a)
                  , forall a. Foldable (WrappedF a)
                  , forall a. Traversable (WrappedF a)
                  ) => Traversable SomeF

This typechecks. However, the last Traversable SomeF is a bit unfortunate in that is uses three separate forall a.s. I attempted to factor this out, like so:

deriving instance (forall a. ( Functor (WrappedF a)
                             , Foldable (WrappedF a)
                             , Traversable (WrappedF a)
                             )) => Traversable SomeF

But then the file no longer typechecked!

$ /opt/ghc/8.6.1/bin/ghc Foo.hs
[1 of 1] Compiling Foo              ( Foo.hs, Foo.o )

Foo.hs:21:1: error:
    • Could not deduce (Functor (F a))
        arising from the superclasses of an instance declaration
      from the context: forall a.
                        (Functor (WrappedF a), Foldable (WrappedF a),
                         Traversable (WrappedF a))
        bound by the instance declaration at Foo.hs:(21,1)-(24,52)
    • In the instance declaration for ‘Traversable SomeF’
   |
21 | deriving instance (forall a. ( Functor (WrappedF a)
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

Foo.hs:21:1: error:
    • Could not deduce (Foldable (F a))
        arising from the superclasses of an instance declaration
      from the context: forall a.
                        (Functor (WrappedF a), Foldable (WrappedF a),
                         Traversable (WrappedF a))
        bound by the instance declaration at Foo.hs:(21,1)-(24,52)
    • In the instance declaration for ‘Traversable SomeF’
   |
21 | deriving instance (forall a. ( Functor (WrappedF a)
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

Foo.hs:21:1: error:
    • Could not deduce (Traversable (F a1))
        arising from a use of ‘traverse’
      from the context: forall a.
                        (Functor (WrappedF a), Foldable (WrappedF a),
                         Traversable (WrappedF a))
        bound by the instance declaration at Foo.hs:(21,1)-(24,52)
      or from: Applicative f
        bound by the type signature for:
                   traverse :: forall (f :: * -> *) a b.
                               Applicative f =>
                               (a -> f b) -> SomeF a -> f (SomeF b)
        at Foo.hs:(21,1)-(24,52)
    • In the second argument of ‘fmap’, namely ‘(traverse f a1)’
      In the expression: fmap (\ b1 -> MkSomeF b1) (traverse f a1)
      In an equation for ‘traverse’:
          traverse f (MkSomeF a1) = fmap (\ b1 -> MkSomeF b1) (traverse f a1)
      When typechecking the code for ‘traverse’
        in a derived instance for ‘Traversable SomeF’:
        To see the code I am typechecking, use -ddump-deriv
   |
21 | deriving instance (forall a. ( Functor (WrappedF a)
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

Richard suspects that this is a bug in the way quantified constraints expands superclasses, so I decided to post it here.

Trac metadata
Trac field Value
Version 8.5
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (Type checker)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information