如何序列化一个Data实例的数据结构?
我想序列化一个由我自己部分定义的数据结构,部分是使用来自外部库(它是Data的一个实例)的数据结构。我想做序列化,而不必定义序列化过程应该如何工作,或换句话说,以一种相当自动的方式。如何序列化一个Data实例的数据结构?
我一直在尝试几个替代方案,我找到了谷歌搜索/问。他们都没有成功。图书馆(genericserialize)似乎我正在寻找。不幸的是,即使对于简单的情况,它也不起作用(如(True,False))。它可能已过时或/和不完整。二进制序列化要求外部数据结构派生二进制(它不)。随着Cereal出现类似的问题。当然,它是Read/Show,但是外部数据结构不会派生Read,所以它也不能被使用。
也许我误解了一些东西。我想,当我第一次面对这个问题时,它会更容易。在其他语言中,比如Erlang,这是以一种非常简单的方式完成的。
你知道图书馆/技术或任何使这个过程尽可能简单吗?
您可以使用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从来没有定义PragmaType
和DefinerType
,我假设他们是()
。
type PragmaType =()
type DefinerType =()
然后我们有一吨的deriving instance
(我们有递归找到所有类型的依赖,并添加Generic
和Binary
他们)。
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
感谢您的快速答复。我试图获得通用的,但我发现了以下错误: 预期的那种 '(* - > *) - > GHC.Prim.Constraint', 但 '通用' 有种“(* - > * ) - > *' 在'Trans'的数据声明中 –
'Trans'的数据定义是什么样子的? – Alec
@SalvadorTamarit实际上,即使链接到图书馆文档也会有帮助... – Alec