2016-07-22 74 views
1

我想序列化一个由我自己部分定义的数据结构,部分是使用来自外部库(它是Data的一个实例)的数据结构。我想做序列化,而不必定义序列化过程应该如何工作,或换句话说,以一种相当自动的方式。如何序列化一个Data实例的数据结构?

我一直在尝试几个替代方案,我找到了谷歌搜索/问。他们都没有成功。图书馆(genericserialize)似乎我正在寻找。不幸的是,即使对于简单的情况,它也不起作用(如(True,False))。它可能已过时或/和不完整。二进制序列化要求外部数据结构派生二进制(它不)。随着Cereal出现类似的问题。当然,它是Read/Show,但是外部数据结构不会派生Read,所以它也不能被使用。

也许我误解了一些东西。我想,当我第一次面对这个问题时,它会更容易。在其他语言中,比如Erlang,这是以一种非常简单的方式完成的。

你知道图书馆/技术或任何使这个过程尽可能简单吗?

回答

2

您可以使用Data.Binary

对于涉及的所有数据类型,派生Generic。这将需要-XDeriveGeneric编译指示。如果您正在使用的外部库的数据类型不这样做,则可能必须有一个orphan instances的模块并使用-XStandaloneDeriving

一旦完成,您可以使用Binary类已支持从Generic派生的事实。您需要启用-XDeriveAnyclass,然后您可以为涉及的所有数据类型添加Binary实例(您可能需要再次为来自外部库的类型创建独立实例)。

编辑

OP added a gist。然后,为了得到这个编译,我们需要添加以下语言编译指示:

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

而下面的进口:

import Language.C.Syntax.AST 
import Language.C.Data.Position 
import Language.C.Data.Node 
import Language.C.Data.Name 
import Language.C.Data.Ident 
import Language.C.Syntax.Constants 

import Data.Data 
import GHC.Generics 
import Data.Binary 

从OP的要点:

type CTypeSpecAnn = CTypeSpecifier NodeAnn 
type CDeclAnn = CDeclaration NodeAnn 
type CDeclSpecAnn = CDeclarationSpecifier NodeAnn 
type CDeclrAnn = CDeclarator NodeAnn 
type CStatAnn = CStatement NodeAnn 
type CExtDeclAnn = CExternalDeclaration NodeAnn 
type CExprAnn = CExpression NodeAnn 
type CBlockItemAnn = CCompoundBlockItem NodeAnn 
type CTranslUnitAnn = CTranslationUnit NodeAnn 

data TransState = 
    TransState 
    { 
     free_node_id :: Int, 
     freeVar :: Int, 
     includes :: [String], 
     fun_defs :: [(String, (CTypeSpecAnn, [CDeclAnn], ([CDeclSpecAnn], CDeclrAnn, [CDeclAnn], NodeAnn)), CStatAnn)], 
     no_fun_defs :: [CExtDeclAnn], 
     last_changed :: String, 
     previous_changes :: ([(String, ((String,CStatAnn,CStatAnn), TransState, [(String, CStatAnn)]))], [(String, ((String,CExprAnn,CExprAnn), TransState, [(String, CStatAnn)]))]), 
     applied_rules :: [String], 
     applicable_rules :: Set String, 
     trans_with_anns :: Bool 
    } 
    deriving (Show, Data, Typeable) 

type NodeAnn = Annotation NodeInfo NodeProperties 
data Annotation nI nP = Ann nI nP 
    deriving (Show, Data, Typeable, Eq) 

data NodeProperties = 
    NodeProperties 
    { 
     _hasSideEffects :: PropertyInfo Bool, 
     _readIn :: PropertyInfo [String], 
     _writeIn :: PropertyInfo [String], 
     _localSymbols :: PropertyInfo [String], 
     _rangeInfo :: PropertyInfo [String], 
     _isCanonical :: PropertyInfo Bool, 
     _isPerfectNest :: PropertyInfo Bool, 
     _hasLoops :: PropertyInfo Bool, 
     _hasFunctionCalls :: PropertyInfo Bool, 
     _hasControlFlowModifiers :: PropertyInfo Bool, 
     _scalarDependences :: PropertyInfo [String], 
     _polcaPragmas :: PropertyInfo [[String]], 
     _allPragmas :: PropertyInfo [String] 
    } 
    deriving (Show, Data, Typeable, Eq) 

data PropertyInfo a = 
    PropertyInfo 
    { 
     _pragmaType :: PragmaType, 
     _definedBy :: DefinerType, 
     _value :: Maybe a 
    } 
    deriving (Show, Data, Typeable, Eq) 

makeLenses ''NodeProperties 
makeLenses ''PropertyInfo 

由于OP从来没有定义PragmaTypeDefinerType,我假设他们是()

type PragmaType =() 
type DefinerType =() 

然后我们有一吨的deriving instance(我们有递归找到所有类型的依赖,并添加GenericBinary他们)。

deriving instance Generic (CDeclaration a) 
deriving instance Binary a => Binary (CDeclaration a) 
deriving instance Generic (CTypeSpecifier a) 
deriving instance Binary a => Binary (CTypeSpecifier a) 
deriving instance Generic (CDeclarationSpecifier a) 
deriving instance Binary a => Binary (CDeclarationSpecifier a) 
deriving instance Generic (CDeclarator a) 
deriving instance Binary a => Binary (CDeclarator a) 
deriving instance Generic (CStatement a) 
deriving instance Binary a => Binary (CStatement a) 
deriving instance Generic (CExternalDeclaration a) 
deriving instance Binary a => Binary (CExternalDeclaration a) 
deriving instance Generic (CExpression a) 
deriving instance Binary a => Binary (CExpression a) 
deriving instance Generic (CCompoundBlockItem a) 
deriving instance Binary a => Binary (CCompoundBlockItem a) 
deriving instance Generic (CTranslationUnit a) 
deriving instance Binary a => Binary (CTranslationUnit a) 
deriving instance Generic (CInitializer a) 
deriving instance Binary a => Binary (CInitializer a) 
deriving instance Generic (CStructureUnion a) 
deriving instance Binary a => Binary (CStructureUnion a) 
deriving instance Generic (CTypeQualifier a) 
deriving instance Binary a => Binary (CTypeQualifier a) 
deriving instance Generic (CStringLiteral a) 
deriving instance Binary a => Binary (CStringLiteral a) 
deriving instance Generic (CAttribute a) 
deriving instance Binary a => Binary (CAttribute a) 
deriving instance Generic (CPartDesignator a) 
deriving instance Binary a => Binary (CPartDesignator a) 
deriving instance Generic (CFunctionDef a) 
deriving instance Binary a => Binary (CFunctionDef a) 
deriving instance Generic (CAssemblyStatement a) 
deriving instance Binary a => Binary (CAssemblyStatement a) 
deriving instance Generic (CAssemblyOperand a) 
deriving instance Binary a => Binary (CAssemblyOperand a) 
deriving instance Generic (CConstant a) 
deriving instance Binary a => Binary (CConstant a) 
deriving instance Generic (CEnumeration a) 
deriving instance Binary a => Binary (CEnumeration a) 
deriving instance Generic (CStorageSpecifier a) 
deriving instance Binary a => Binary (CStorageSpecifier a) 
deriving instance Generic (CDerivedDeclarator a) 
deriving instance Binary a => Binary (CDerivedDeclarator a) 
deriving instance Generic (CBuiltinThing a) 
deriving instance Binary a => Binary (CBuiltinThing a) 
deriving instance Generic (CArraySize a) 
deriving instance Binary a => Binary (CArraySize a) 
deriving instance Generic (Flags a) 
deriving instance Binary a => Binary (Flags a) 
deriving instance Generic NodeInfo 
deriving instance Binary NodeInfo 
deriving instance Generic Name 
deriving instance Binary Name 
deriving instance Generic Ident 
deriving instance Binary Ident 
deriving instance Generic CString 
deriving instance Binary CString 
deriving instance Generic CStructTag 
deriving instance Binary CStructTag 
deriving instance Generic CFloat 
deriving instance Binary CFloat 
deriving instance Generic CChar 
deriving instance Binary CChar 
deriving instance Generic CUnaryOp 
deriving instance Binary CUnaryOp 
deriving instance Generic CBinaryOp 
deriving instance Binary CBinaryOp 
deriving instance Generic CInteger 
deriving instance Binary CInteger 
deriving instance Generic CAssignOp 
deriving instance Binary CAssignOp 
deriving instance Generic CIntFlag 
deriving instance Binary CIntFlag 
deriving instance Generic CIntRepr 
deriving instance Binary CIntRepr 

deriving instance Binary TransState 
deriving instance Generic TransState 
deriving instance Generic (Annotation a b) 
deriving instance (Binary a, Binary b) => Binary (Annotation a b) 
deriving instance Generic NodeProperties 
deriving instance Binary NodeProperties 
deriving instance Generic (PropertyInfo a) 
deriving instance Binary a => Binary (PropertyInfo a) 

作为一个侧面说明,这些实例下半年可在类型的数据声明自行申报(因为这些在当前文件中声明)。一个棘手的问题是,我们仍然没有Binary实例Position。我们不能自动派生它,因为它的数据构造函数没有被导出。但是,没有任何东西阻止我们编写手册Binary实例。

instance Binary Position where 
    put p | isNoPos p = putWord8 0 
      | isBuiltinPos p = putWord8 1 
      | isInternalPos p = putWord8 2 
      | isSourcePos p = putWord8 3 >> put (posOffset p) >> put (posFile p) >> put (posRow p) >> put (posColumn p) 

    get = do 
     marker <- getWord8 
     case marker of 
      0 -> return nopos 
      1 -> return builtinPos 
      2 -> return internalPos 
      3 -> position <$> get <*> get <*> get <*> get 
+0

感谢您的快速答复。我试图获得通用的,但我发现了以下错误: 预期的那种 '(* - > *) - > GHC.Prim.Constraint', 但 '通用' 有种“(* - > * ) - > *' 在'Trans'的数据声明中 –

+0

'Trans'的数据定义是什么样子的? – Alec

+0

@SalvadorTamarit实际上,即使链接到图书馆文档也会有帮助... – Alec