Reputation: 16833
I need to serialize a data type to disk that uses Data.Text
, here's an example:
{-# 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
As written, this generates the error:
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'
If I uncomment the instance Serialize Text
line, then this more cryptic error comes about:
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'
I could implement the Serialize
instance manually, but this seems like a situation where orphaned instances would be a real problem, and furthermore, I don't think I know enough about Data.Text
to serialize / deserialize it quickly and correctly.
Is there a standard solution to this problem? (I'm also not wedded to using cereal's Serialize instance, but I have been having some version issues relating to using the binary package; binary-0.5.1.1 doesn't seem to support Generics well, and I'd like to avoid writing boilerplate.)
Upvotes: 7
Views: 975
Reputation: 13750
In order to address this issue, I just published cereal-text
on Hackage.
The implementation is similar to rcreswick's answer, however cereal-text
also provides an instance for lazy text.
Install the library using cabal install cereal-text
and import the instances using:
import Data.Serialize.Text ()
Note that for some applications safecopy
is not usable, because it depends on Template Haskell which is not available on all platforms.
Upvotes: 3
Reputation: 16833
Here's the instance I ended up using, based on Joachim Britner's advice:
instance Serialize Text where
put txt = put $ encodeUtf8 txt
get = fmap decodeUtf8 get
As pointed out, you may need different encode / decode functions, but the structure should be the same.
Upvotes: 5
Reputation: 25782
I believe that the missing instance should be considered a feature: Data.Text
talks about text, which should be kept distinct from its representation. So the canonical way to approach the problem is to encode the Data.Text
to a Data.ByteString
in the encoding you want it to be (or, better, some specification or metadata wants it to be), and then serialize the Data.ByteString
.
The most common encoding functions can be found in Data.Text.Encoding.
Upvotes: 4