Reputation: 3285
The text package does not provide an instance of Binary
to encode/decode text. I have read about and understand the reasoning behind this (namely, Text
should be encoding-agnostic). However, I need a Binary
instance of Text
. I've found that there is a package called text-binary that does this. However, the instance is as follows:
instance Binary T.Text where
put = put . T.encodeUtf8
get = T.decodeUtf8 <$> get
Pretty good, except that decodeUtf8
is a partial function, so I'd rather be using decodeUtf8'
and passing the failure through the Get
monad. I can't figure out how to fail correctly with the Get
monad. Just from looking around in Data.Binary.Get, I see this:
data Decoder a = Fail !B.ByteString {-# UNPACK #-} !ByteOffset String
| Partial (Maybe B.ByteString -> Decoder a)
| Done !B.ByteString {-# UNPACK #-} !ByteOffset a
Which seems to indicate that there is a way to do what I want. I just can't see how the library authors intend for it to be used. I appreciate any insights that a more learned mind than my own has to offer.
Upvotes: 2
Views: 134
Reputation: 120741
Well, though we tend to disregard it, the Monad
class still has that yucky fail
method:
get = do
utf8'd <- get
case T.decodeUtf8' utf8'd of
Just t -> return t
Nothing -> fail "No parse for UTF-8 Text"
I'm not sure if it should still be considered "correct" to use fail
, but it seems to be the obvious thing for a case like this. I suppose even if it's removed from the Monad
class, there'll be some other class MonadPlus m => MonadFail m where fail :: String -> m a
which Get
will be an instance of.
Upvotes: 4