I have a datatype used to aggregate some statistics, it looks like this:
data DataType = DataType
{ a :: Int
, b :: Int
}
Furthermore, I would like to use it for folds, so a semigrop/monoid
instance would be useful, which I imagined I might get like this:
deriving (Semigroup, Monoid) via (Sum Int, Sum Int)
or this
deriving (Semigroup, Monoid) via Generically (Sum Int, Sum Int)
But it doesn’t work, the error message says they are not equivalent:
1. • Couldn't match representation of type ‘(Sum Int, Sum Int)’
with that of ‘DataType’
However, using a newtype does work:
newtype NewType = NewType (Int, Int)
deriving stock (Show, Generic)
deriving (Semigroup, Monoid) via (Sum Int, Sum Int)
Just to be sure I wasn’t having some obvious mistake lingering in my code, I pasted the Rep
of the datatypes into a text-differ, which looked like this.
I’m very sorry if the quality is very poor on your display, I didn’t know how to properly format the diff using this markdown.
Nevertheless, at least concerning the generics, they seem to representationally equivalent! (All the differences are metadata or newtype wrappers, which are equivalent when the Constructor is in Scope)
Whilst searching around for solutions I discovered this discussion which recommended Generic.Data.Surgery
Unaware of this the Surgery
module, I had hacked together my own Solution using Coercible
constraints on Generic Representations.
Leading up to the question in the title, when are two datatype representations considered equivalent by GHC, allowing for DerivingVia
?