Why do the generic classes allow `V1` void datatypes, which can't be en/decoded?
raehik opened this issue · 3 comments
In Data.Aeson.Types.ToJSON
and Data.Aeson.Types.FromJSON
, instances are provided for V1
types, which is the generic representation for void datatypes such as data Void
.
Why are these runtime errors and not compile-time errors? ToJSON Void
and FromJSON Void
instances are useful because Void
is a concrete type, so the explicitness makes me comfortable that a user would expect an error (and perhaps wants one). In the general case i.e. for the abstract void datatype, I feel a compile-time error is more appropriate. Better no instance than an absurd one!
This was originally introduced by #661 . Void
and V1
were added together. User bergmark added that they had originally avoided V1
in another library. I wasn't able to find much discussion. I think it would be good to figure out
- if
V1
en/decoding instances are sensible and useful in practice, in which case no need to change - if we can emit a useful type error for all the GHC versions aeson supports (see below), in which case this is a harder sell
In such cases where the V1
instance is hit, it's possible to emit a pretty type error for the user (code taken from here):
-- | Refuse to derive instance for void datatype.
instance TypeError GErrRefuseVoid => GPut V1 where
gput = undefined
type GErrRefuseVoid =
'Text "Refusing to derive binary representation for void datatype"
I would gladly make this change if it's found appropriate.
I agree that the instance seems of dubious usefulness. But it doesn't seem harmful either, so I would still lean towards not changing the status quo.
Perhaps there is a use case in a prototyping scenario, where you sketch out the types of your application and leave some empty to fill them out later (but one could also make them a unit type with a TODO constructor, with essentially the same effect).
Another potential use case is if you're automatically generating Haskell code, having V1
lets you use deriving uniformly for all generated types.
I note that deriving stock instances like Show
, Eq
, Ord
all work on empty data types, so my suggestion might not be consistent with the rest of the Haskell ecosystem. Which isn't to say it's the wrong idea -- I feel recent language changes have been moving away from the fairly implicit nature of instance deriving (e.g. DerivingVia) -- but I'm now a bit less sure about pushing this through aeson.
I agree that the instance seems of dubious usefulness. But it doesn't seem harmful either, so I would still lean towards not changing the status quo.
I do think they are slightly harmful, as disallowing V1
may allow aeson to catch some programmer errors.