Ell*_*ask 5 serialization haskell types deserialization
我正在尝试使用read和show进行序列化/反序列化(这本身不是问题),但在某种意义上可以扩展(但不能缩小)数据类型.
假设我有这种类型:
data Foo = { bar :: Int } deriving (Show, Read)
Run Code Online (Sandbox Code Playgroud)
列表:
foos = [Foo 1, Foo 2]
Run Code Online (Sandbox Code Playgroud)
我可以轻松地将其反序列化为一个文件:
hPutStrLn fileHand . ppShow $ foos
Run Code Online (Sandbox Code Playgroud)
然后我可以序列化它:
!str <- hGetContents fileHand
let foosFromFile = fromMaybe [] $ (readMaybe :: String -> Maybe [Foo]) str
Run Code Online (Sandbox Code Playgroud)
但是假设几个月后我想在Foo类型中添加一个'baz'字段.旧格式文件的直接序列化将不再适用于读取,我将需要转换文件(我真的不想要).
那么,是否有一个优雅的(没有在程序本身中放置明确的版本控制逻辑)解决方案仍然序列化文件中的数据,并用默认值填充缺少的字段?也许某些类型的技巧?
谢谢.
是的。只需添加一个多态字段:
data Foo a = { bar :: Int, extra :: a } deriving (Show, Read)
Run Code Online (Sandbox Code Playgroud)
然后定义一个序列化实例,其约束a必须是可序列化的:
instance (Serialize a) => Serialize (Foo a) where ...
Run Code Online (Sandbox Code Playgroud)
当您不使用额外字段时,只需将 a 插入()其中,因为()它可以轻松序列化(并且已经有一个Serialize实例)。
编辑:哎呀,刚刚意识到你在谈论漂亮的印刷。等效的解决方案是定义一个类型类,如下所示:
class PrettyPrint a where
pp :: a -> String
instance PrettyPrint () where
pp () = ""
instance (PrettyPrint a) => PrettyPrint (Foo a) where
pp = ... -- You fill this in
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
319 次 |
| 最近记录: |