Reputation: 41
Let's say I need to do write/read of a Data.Time.UTCTime
in "%Y-%m-%d %H:%M:%S" format many many times to/from a file.
It seems to me that, using Data.Time.formatTime
or Data.Time.parseTime
to convert UTCTime
to/from String
and then packing/unpacking the String
to/from ByteString
, would be too slow since it involves an intermediate String
. But writing a ByteString
builder/parser of UTCTime
by hand seems like repeating a lot of work already done in formatTime
and parseTime
.
I guess my question is: Is there a systematic way to get functions of type t -> String
or String -> t
converted to t -> ByteString
or ByteString -> t
with increased efficiency without repeating a lot of work?
I am totally a Haskell newbie, so please forgive me if the question is just stupid.
Upvotes: 4
Views: 1289
Reputation: 20980
If you're not really in the need of heavily optimized code, the usual and easiest way is to use function composition:
timeToByte = toBytes . formatTime
byteToTime = parseTime . fromBytes
or something like that, as I'm not familiar with those libraries.
If after profiling you recognize that this approach is still to slow, I guess you will have to write something by hand.
Upvotes: -3
Reputation: 668
No, there isn't a general way to convert a function of type t -> String
to one of type t -> ByteString
. It might help you reconcile yourself to that reality if you recall that a ByteString isn't just a faster String
; it's lower-level than that. A ByteString
is a sequence of bytes; it doesn't mean anything more unless you have an encoding in mind.
So your options are:
Use function composition, as in phg's answer:
import Data.ByteString.Char8 as B
timeToByteStr :: UTCTime -> ByteString
timeToByteStr = B.pack . formatTime'
parseBStrTime :: ByteString -> Maybe UTCTime
parseBStrTime = parseTime' . B.unpack
where I've corrected the function names. I've also used, e.g., parseTime' instead of parseTime, to elide over the format string and TimeLocale
you need to pass in.
(It's also worth noting that Data.Text
is often a better choice than Data.ByteString.Char8
. The latter only works properly if your Char
s fall in Unicode code points 0-255.)
If performance is an issue and this conversion profiles out as a bottleneck, write a parser/builder.
String
s.The last option is an underrated choice for Haskell newbies, IMHO. String
is suboptimal, performance-wise, but it's not spawn-of-the-Devil. If you're just getting started with Haskell, why not keep your life as simple as possible, until and unless your code becomes too slow?
Upvotes: 5