Search code examples
haskellghcderived-instances

Using -XGeneralizedNewtypeDeriving with -XMultiParamTypeClasses


The following code results in an error:

{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, StandaloneDeriving #-}

class Module a b where
    (*>) :: a -> b -> b

data D
newtype DWrapper = DW D    
instance Module D D    
deriving instance Module DWrapper DWrapper

The error:

No instance for (Module DWrapper D) arising from a use of ‘Main.*>’
In the first argument of ‘GHC.Prim.coerce’, namely
  ‘(Main.*>) :: DWrapper -> D -> D’
In the expression:
    GHC.Prim.coerce ((Main.*>) :: DWrapper -> D -> D) ::
      DWrapper -> DWrapper -> DWrapper
In an equation for ‘*>’:
    (*>)
      = GHC.Prim.coerce ((Main.*>) :: DWrapper -> D -> D) ::
          DWrapper -> DWrapper -> DWrapper
When typechecking the code for  ‘Main.*>’
  in a derived instance for ‘Module DWrapper DWrapper’:
  To see the code I am typechecking, use -ddump-deriv

So GHC is looking for a Module DWrapper D instance to derive the requested Module D D instance. This is reasonable I guess, but not what I intended. Is there a way to tell GHC which instance to derive from? How does GNTD work on MPTCs?


Solution

  • Unfortunately, GeneralizedNewtypeDeriving only works on the last parameter of a multi-parameter typeclass. Even with standalone deriving:

    • The stand-alone syntax is generalised for newtypes in exactly the same way that ordinary deriving clauses are generalised (Section 7.5.5, “Generalised derived instances for newtypes”). For example:

      newtype Foo a = MkFoo (State Int a)
      deriving instance MonadState Int Foo
      

      GHC always treats the last parameter of the instance (Foo in this example) as the type whose instance is being derived.

    (BTW, I tried searching for any relevant GHC trac bug report or feature request, but couldn't find any.)