Adding deriving (Data) to standard types
Question
I would like to add deriving (Data)
to standard types. After enabling the StandaloneDeriving
, FlexibleContexts
, DeriveDataTypeable
, and UndecidableInstances
extensions, ghc accepts
deriving instance Data Day => Data (Day)
However, if I do the same thing for DiffTime
I get
TemperatureRecord.hs:30:0: The data constructors of `DiffTime' are not all in scope so you cannot derive an instance for it In the stand-alone deriving instance for `(Data DiffTime) => Data (DiffTime)'
I am doing all this to help autogenerate binary instances of standard types. So I have two questions:
- How do I solve the error I am getting with
DiffTime
, and - What is the right way to make standard library types binary serializable in Haskell?
Solution
The time
package does not expose MkDiffTime
, DiffTime
's constructor.
To create a Data
instance, you would normally work with the type's constructors. Even if you are automatically deriving it, that's what the derived instance would do as well.
Luckily, this could be worked around, to some extent. You can extract the data from a DiffTime
using toRational
, and you can wrap a number in a DiffTime
using fromRational
. So it should be possible to "fake" a Data
instance with a "fake" constructor. This would be done "manually" (no deriving).
As to why the constructor of DiffTime
isn't exposed - this would be similar to the reasoning behind private
in C++ et al. This gives the creators of DiffTime
the freedom to change its implementation without breaking anything. Indeed, if they would change the structure, it won't break your "fake" Data
instance and will not break your serialization format.
OTHER TIPS
I am a haskell newb, but I think you can do this to expose the constructor (and thus automatically derived Data)
cabal unpack time
change
newtype DiffTime = MkDiffTime Pico deriving (Eq,Ord
to
data DiffTime = MkDiffTime Pico deriving (Eq,Ord
and cabal install seems to work