Derived instance in Haskell
Asked Answered
S

1

8

I would like to use derived instance like this:

data Test3D = forall a. (Show a, Eq a, Typeable a, Generic a)
                => Test3D { testDt :: String
                          , testPrm :: a
                          }
   deriving (Show, Eq, Typeable, Generic)

instance Binary (Test3D)
$(deriveJSON defaultOptions ''Test3D)

But I received from GHC:

• Can't make a derived instance of ‘Show Test3D’:
        Constructor ‘Test3D’ has existentials or constraints in its type
        Possible fix: use a standalone deriving declaration instead
• In the data declaration for ‘Test3D’

This way is very convenient for my project. I can not find the solution.

Is any way of using derived instance for such data?

Someway answered 4/9, 2017 at 6:39 Comment(3)
How would you write the instance yourself? Even writing out the type signature will prove difficult, if you want to show any information about the testPrm. If you can't figure out how to do it, then GHC can't do it automatically for you. On the other hand, if you don't care about showing testPrm, then the instance is easy to write by hand and you don't need to derive it.Restless
This involves writing a Binary instance for every Generic. It looks as a rather complex task. I think we can't realistically hope that the automagic deriving mechanism solved this for us. Perhaps we could manually write an easier instance if we use Binary a instead of Generic a?Semifluid
Maybe I'm not correctly implementing my idea. I just want to have some type of data, which in turn contains a field with an unknown type. But the field type meets a certain requirement through type classes. And all of them should be (Show a, Eq a, Typeable a, Generic, ...).Someway
M
10

Is any way of using derived instance for such data?

Yes. Do what GHC suggested, make a standalone deriving clause:

{-# LANGUAGE StandaloneDeriving, ExistentialQuantification #-}

data Test3D = forall a. (Show a)
                => Test3D { testDt :: String
                          , testPrm :: a
                          }

deriving instance Show Test3D

What you cannot do is derive an Eq instance, because different values may actually contain different types and it's only possible to compare these with a dynamic-cast hack through Typeable.

Magical answered 4/9, 2017 at 13:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.