2016-07-22 5 views
1

私は自分自身で部分的に定義されたデータ構造をシリアル化したいし、部分的には外部ライブラリ(Dataのインスタンス)からのデータ構造を使用しています。私は、シリアライゼーションプロセスをどのように動作させるか、あるいは、むしろ自動化する方法を定義することなく、シリアライゼーションを行いたいと思っていました。Dataのインスタンスであるデータ構造をシリアル化する方法は?

私は、グーグル/尋問で見つけたいくつかの選択肢を試してきました。いずれも成功しなかった。図書館(genericserialize)は私が探していたようでした。残念ながら、(True、False)のような単純なケースでも動作しません。おそらく時代遅れであるか、不完全なものです。バイナリシリアル化では、外部データ構造がバイナリを導出する必要があります(バイナリは取得しません)。 Cerealと同様の問題が発生する。もちろん、それはRead/Showですが、外部データ構造はReadを導出しないので、どちらも使用できません。

多分私は何かを誤解しています。私はこの問題に直面したときにそれがより簡単になると思った。たとえばErlangのような他の言語では、これは非常に簡単な方法で行われます。

ライブラリ/技術など、このプロセスをできるだけ簡単にすることが分かりますか?

答えて

2

Data.Binaryを使用できます。

関連するすべてのデータ型についてGenericを導出します。これには-XDeriveGenericプラグマが必要です。使用している外部ライブラリのデータ型がこれをしない場合は、モジュールをorphan instancesにして-XStandaloneDerivingを使用する必要があります。

これが完了すると、Binaryクラスが既にGenericから派生することをサポートしているという事実を利用できます。 -XDeriveAnyclassを有効にしてから、関連するすべてのデータタイプに対してBinaryのインスタンスを追加できます(外部ライブラリのタイプのスタンドアロンインスタンスが必要な場合があります)。

EDIT

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 

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 =() 

その後、我々は(我々は再帰的にすべてのタイプの依存関係を見つけ、それらにGenericBinaryを追加する必要があります)deriving instanceのトンを持っています。サイドノートとして

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) 

(それらが現在のファイルで宣言されているので)、それらのインスタンスの後半は、型自体のデータ宣言で宣言することができます。 1つの点は、PositionのインスタンスがまだBinaryでないことです。データコンストラクタがエクスポートされていないため、自動的に派生することはできません。しかし、手動で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'、 'Generic'には種類があります(* - > *)。次のエラーが表示されます。 ) - > * ' ' Trans''のデータ宣言で –

+0

'Trans'のデータ定義はどのように見えますか? – Alec

+0

@SalvadorTamarit実際には、図書館のドキュメントへのリンクさえも役に立ちます... – Alec

関連する問題