user1747134
user1747134

Reputation: 2482

Deriving in newtype with more type variables

newtype MyNewtype1 f v = MyNewtype1 { getVal1 :: f v } deriving Eq -- OK
newtype MyNewtype2 f maybe v = MyNewtype2 { getVal2 :: f (maybe v) } deriving Eq --OK
newtype MyNewtype3 f v = MyNewtype3 { getVal3 :: f (Maybe v) } --  OK
newtype MyNewtype4 f v = MyNewtype4 { getVal4 :: f (Maybe v) } deriving Eq --NOT OK

I have these newtypes. The first three work as expected, but the fourth gives:

    • No instance for (Eq (f (Maybe v)))
        arising from the 'deriving' clause of a data type declaration
      Possible fix:
        use a standalone 'deriving instance' declaration,
          so you can specify the instance context yourself
    • When deriving the instance for (Eq (MyNewtype4 f v))

I can't understand where is the problem. It seems to me, that the second newtype is strictly more general and thus have to suffer the same problem. So if MyNewtype2 can derive Eq, why MyNewtype2 can not? That's probably what confuses me the most. Could somebody please explain this to me? Also, what is the preferred solution to if I want a newtype like that?

Upvotes: 3

Views: 264

Answers (2)

leftaroundabout
leftaroundabout

Reputation: 120751

I don't know why 2 works but 4 doesn't. Probably has something to do with flexible contexts (which I don't understand well enough to explain).

To answer the second question... the preferred solution if you want a newtype like that is as GHC suggested: to use a standalone deriving instance.

{-# LANGUAGE StandaloneDeriving, FlexibleContexts, UndecidableInstances #-}

newtype MyNewtype4 f v = MyNewtype4 { getVal4 :: f (Maybe v) }
deriving instance (Eq (f (Maybe v))) => Eq (MyNewtype4 f v)

Upvotes: 4

Related Questions