为Data.Text序列化实例?

时间:2013-10-14 17:10:18

标签: haskell serialization

我需要将数据类型序列化为使用Data.Text的磁盘,这是一个例子:

{-# LANGUAGE DeriveGeneric #-}
import Data.Serialize (Serialize)
import Data.Text (Text)
import GHC.Generics

data Foo = Foo Text deriving (Read, Show, Eq, Ord, Generic)
instance Serialize Foo
-- instance Serialize Text

如上所述,这会产生错误:

No instance for (Serialize Text)
  arising from a use of `Data.Serialize.$gdmput'
Possible fix: add an instance declaration for (Serialize Text)
In the expression: (Data.Serialize.$gdmput)
In an equation for `put': put = (Data.Serialize.$gdmput)
In the instance declaration for `Serialize Foo'

如果我取消注释instance Serialize Text行,则会出现更加神秘的错误:

No instance for (Data.Serialize.GSerialize (Rep Text))
  arising from a use of `Data.Serialize.$gdmput'
Possible fix:
  add an instance declaration for
  (Data.Serialize.GSerialize (Rep Text))
In the expression: (Data.Serialize.$gdmput)
In an equation for `put': put = (Data.Serialize.$gdmput)
In the instance declaration for `Serialize Text'

我可以手动实现Serialize实例,但这似乎是一个孤立实例会成为真正问题的情况,而且,我认为我对Data.Text序列化/不够了解快速正确地反序列化。

这个问题有标准解决方案吗? (我也没有坚持使用Grain的Serialize实例,但我一直有一些与使用二进制包有关的版本问题; binary-0.5.1.1似乎不能很好地支持泛型,我想避免写样板。)

3 个答案:

答案 0 :(得分:5)

以下是我最终使用的实例,基于Joachim Britner的建议:

instance Serialize Text where
  put txt = put $ encodeUtf8 txt
  get     = fmap decodeUtf8 get

正如所指出的,您可能需要不同的编码/解码功能,但结构应该相同。

答案 1 :(得分:4)

我认为缺少的实例应该被视为一个特征:Data.Text谈论文本,应该保持与其表示不同。因此,解决问题的规范方法是将Data.Text编码为您希望的编码中的Data.ByteString(或者,更好的是,某些规范或元数据希望它是),然后序列化Data.ByteString

最常见的编码功能可以在Data.Text.Encoding

中找到

答案 2 :(得分:3)

为了解决这个问题,我刚刚在Hackage上发布了cereal-text

实现与rcreswick's answer类似,但cereal-text也提供了延迟文本的实例。

使用cabal install cereal-text安装库并使用以下命令导入实例:

import Data.Serialize.Text ()

请注意,对于某些应用程序safecopy不可用,因为它依赖于模板Haskell,而这在所有平台上都不可用。