Кажется, мой вопрос тесно связан с этим
один.
Мой код анализирует файл yaml, переупорядочивает объекты и записывает новый файл yaml. Он отлично работает, но в нем есть особенно уродливая часть.
Я должен объявить свои структуры данных как экземпляры FromJson
и ToJson
следующим образом:
instance FromJSON Users where
parseJSON = genericParseJSON (defaultOptions { fieldLabelModifier = body_noprefix })
instance ToJSON Users where
toJSON = genericToJSON (defaultOptions { fieldLabelModifier = body_noprefix })
Проблема в том, что я должен повторить это для 8 или около того других случаев:
instance FromJSON Role where
parseJSON = genericParseJSON (defaultOptions { fieldLabelModifier = body_noprefix })
instance ToJSON Role where
toJSON = genericToJSON (defaultOptions { fieldLabelModifier = body_noprefix })
...
...
Я не мог понять, как избежать этого повторения. Есть ли какой-нибудь метод, чтобы объявить две функции только один раз (например, в новом классе) и позволить всем этим типам данных наследоваться от него?
Решение (см. Также принятый ответ от dfeuer):
Мне лично нравится это решение. Вам нужно будет добавить
{-# language DerivingVia #-}
{-# language UndecidableInstances #-}
newtype NP a = NP {unNP::a}
instance (Generic a, GFromJSON Zero (Rep a)) => FromJSON (NP a) where
parseJSON = fmap NP . genericParseJSON
(defaultOptions { fieldLabelModifier = body_noprefix })
instance (Generic a, GToJSON Zero (Rep a)) => ToJSON (NP a) where
toJSON = genericToJSON (defaultOptions { fieldLabelModifier = body_noprefix }) . unNP
Затем вы можете объявить типы следующим образом:
data User = User { ... } deriving (Show, Generic)
deriving FromJSON via (NP User)
deriving ToJSON via (NP User)