2

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?

crockeea
  • 21,651
  • 10
  • 48
  • 101
  • I'm not at my computer right now, but you might try standalone deriving. If that doesn't work, you can build it manually using coercions if you need the efficiency boost. – dfeuer Oct 20 '15 at 20:43
  • @dfeuer I am using `StandaloneDeriving`, see the language pragmas. I'm not concerned about efficiency per se, really just expediency. – crockeea Oct 20 '15 at 20:46
  • Oh, sorry, I didn't look closely enough. No, you can't really tell `deriving` what to do the way you're trying to, and `MPTC` is throwing a wrench into the machine. I don't know if a functional dependency would help anything even if one were acceptable to you. – dfeuer Oct 20 '15 at 20:58
  • 2
    I reckon fundeps wouldn't help either, at least I have run into error messages along the lines “can't derive instance with associated type, not even with cunning generalized deriving”. — No, I really don't think it's possible to derive instances like this, at all. Should be a pretty tractable job for TH or even CPP, though. – leftaroundabout Oct 20 '15 at 21:38

1 Answers1

5

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.)

Ørjan Johansen
  • 18,119
  • 3
  • 43
  • 53
  • 3
    There are no tickets because it is not a bug. The only way to do this without ambiguity would be to allow the programmer to specify which instance to derive from. – dfeuer Oct 21 '15 at 03:04