2017-08-08 8 views
2

J'ai un module Foo.hs qui contient une définition qui ne dérive pas Generic:dériver Generic et ToJSON en même temps?

-- Foo.hs 
data Blather = Blather ... -- Generic not derived here 

Et dans un autre module Je veux tirer ToJSON:

-- Bar.hs 
{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-} 

import GHC.Generics 
import Data.Aeson 

instance Generic Blather 
instance ToJSON Blather 

mais il ne compile pas. Si je dérive générique dans Foo.hs sur le site de définition, je peux plus tard dériver ToJSON dans un autre module.

Puis-je dériver ToJSON Blather dans Bar.hs sans modifier l'original Foo.hs?

Ou existe-t-il un moyen simple d'écrire instance ToJSON Blather à la main?

+0

t-il avec le [ 'l'extension StandaloneDeriving'] (https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/deriving.html)? –

+0

Pourquoi ne voulez-vous pas dériver 'Generic' où vous définissez le type? Les instances orphelines sont mauvaises! – dfeuer

+0

Oui, ce serait la bonne solution, mais à ce stade, je ne veux pas soumettre un PR qui modifie 'Foo.hs'. – ErikR

Répondre

4

Activez StandaloneDeriving et utilisez deriving instance ... car cela ne nécessite pas que la dérivation se trouve dans le même module que le type de données.

Exemple:

{-# LANGUAGE DeriveGeneric, StandaloneDeriving, DeriveAnyClass #-} 

import GHC.Generics 
import Data.Aeson 
import Foo 

deriving instance Generic Blather 
deriving instance ToJSON Blather 

main = undefined 
+0

Ah - Je suivais la recette [ici] (https://artyom.me/aeson#records-and-json-generics) et j'utilisais juste 'instance ...' pas 'deriving instance'. – ErikR

+1

@ErikR Donner une déclaration d'instance vide fonctionne pour 'ToJSON', mais pas pour' Generic'. Les raisons sont un peu subtiles: 'Generic' est une classe pour laquelle la dérivation est intégrée. 'ToJSON' est une classe pour laquelle des" signatures par défaut "génériques et des implémentations sont données. – kosmikus