2017-08-08 57 views
2

我有一个模块Foo.hs其中包含不派生Generic一个定义:同时派生Generic和ToJSON?

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

而在另一个模块我想获得ToJSON

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

import GHC.Generics 
import Data.Aeson 

instance Generic Blather 
instance ToJSON Blather 

但它不会编译。如果我在定义站点的Foo.hs中推导出Generic,则我可以稍后在另一个模块中推导出ToJSON

我可以在Bar.hs中得出ToJSON Blather而无需修改原始Foo.hs

或者有没有简单的方法手写instance ToJSON Blather

+0

它是否与['StandaloneDeriving'分机]工作(https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/deriving.html )? –

+0

为什么你不想在你定义类型的地方派生'Generic'?孤儿实例是邪恶的! – dfeuer

+0

是的,这将是正确的解决方案,但在此时我不想提交修改'Foo.hs'的PR。 – ErikR

回答

4

启用StandaloneDeriving并使用deriving instance ...,因为这并不要求派生与数据类型在同一模块中。

实施例:

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

import GHC.Generics 
import Data.Aeson 
import Foo 

deriving instance Generic Blather 
deriving instance ToJSON Blather 

main = undefined 
+0

啊 - 我按照[这里]的配方(https://artyom.me/aeson#records-and-json-generics),只是使用'instance ...'而不是'派生实例'。 – ErikR

+1

@ErikR给出一个空的实例声明适用于'ToJSON',但不适用于'Generic'。原因有点微妙:'Generic'是派生内置的类。 'ToJSON'是一个通用的“默认签名”和实现给出的类。 – kosmikus