我需要将数据类型序列化为使用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似乎不能很好地支持泛型,我想避免写样板。)
答案 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,而这在所有平台上都不可用。