7

我需要将数据类型序列化到使用 的磁盘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快速正确地序列化/反序列化它了解不够。

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

4

3 回答 3

5

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

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

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

于 2013-10-15T15:27:44.993 回答
4

我认为缺失的实例应该被认为是一个特征:Data.Text谈论文本,应该与它的表示区分开来。Data.Text因此,解决问题的规范方法是Data.ByteStringData.ByteString.

最常见的编码函数可以在Data.Text.Encoding中找到。

于 2013-10-14T17:39:42.707 回答
3

为了解决这个问题,我刚刚cereal-text在 Hackage 上发表了文章。

该实现类似于rcreswick 的 answer,但cereal-text也提供了惰性文本的实例。

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

import Data.Serialize.Text ()

请注意,对于某些应用程序safecopy不可用,因为它依赖于并非在所有平台上都可用的 Template Haskell。

于 2014-04-26T00:16:20.830 回答