Skip to content

Impossible newtype derivation on too polymorphic class definition

Summary

I'm trying to derive a type class instance with a single method creating a value parameterized with the class's type and a fix parametric type.

Doing so, it does not compile.

Steps to reproduce

I have the following code:

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Bug where

data Deserializer m a = Deserializer {downWay :: String -> m a}

class Cls a where
  mkDeserializer :: a -> Deserializer Maybe a

newtype Tac = Tac String

instance Cls Tac where
  mkDeserializer _ = Deserializer $ Just . Tac

newtype Toc = Toc Tac
  deriving newtype (Cls)

Which fails with:

[1 of 1] Compiling Bug              ( Bug.hs, Bug.o ) [Source file changed]

Bug.hs:17:21: error:
    • Couldn't match type ‘Tac’ with ‘Toc’
        arising from the coercion of the method ‘mkDeserializer’
          from type ‘Tac -> Deserializer Maybe Tac’
            to type ‘Toc -> Deserializer Maybe Toc’
    • When deriving the instance for (Cls Toc)
   |
17 |   deriving newtype (Cls)
   |                     ^^^

While, fixing the parametric type work:

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Bug where

data Deserializer a = Deserializer {downWay :: String -> Maybe a}

class Cls a where
  mkDeserializer :: a -> Deserializer a

newtype Tac = Tac String

instance Cls Tac where
  mkDeserializer _ = Deserializer $ Just . Tac

newtype Toc = Toc Tac
  deriving newtype (Cls)

Expected behavior

It should compile, independently of the data's structure.

Environment

  • GHC version used:
    • 9.0.2
    • 9.2.3
    • 9.4.0.20220721

Optional:

  • Operating System: NixOS (22.10 / unstable)
  • System Architecture: x86_64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information