Closed ocharles closed 4 years ago
Yes! This transformation to apply a type constructor to every field is the OnFields
(micro)surgery.
You can then use Surgery'
to "apply a surgery", i.e., modify the Generic
instance of a type. So Surgery' (OnFields Sum) PalletUsage
has a Generic
instance as if you wrote
data PalletUsage =
PalletUsage
{ pallets :: Sum Rational
, strips :: Sum Rational
}
And then you can derive Semigroup
and Monoid
for PalletUsage
via GenericProduct (Surgery' (OnFields Sum) PalletUsage)
.
(It turns out you have to use GenericProduct
here, while Generically
isn't well-suited for deriving Monoid
via surgeries because of its new Monoid
instance...)
{-# LANGUAGE DeriveGeneric, DerivingVia #-}
module B where
import Data.Monoid
import GHC.Generics (Generic)
import Generic.Data (GenericProduct(..))
import Generic.Data.Microsurgery
data PalletUsage = PalletUsage Rational Rational
deriving (Show, Generic)
deriving (Semigroup, Monoid) via SumSurgery PalletUsage
type SumSurgery a = GenericProduct (Surgery' (OnFields Sum) a)
There are some things here I could add to the documentation, so thanks for the question!
Ah, very nice! This answers my question, thank you! Do you want to leave this open to write docs? And thank you for a very very nice library, it's really changing how we write code at work
You're welcome!
Yes, let's keep this open as a reminder, I'll get to it at the end of the week.
This may already be possible, but I want to define a
Monoid
instance for:by viewing it as isomorphic to
(Sum Rational, Sum Rational)
.Could this be done with some kind of microsurgery?