For producing output the highest performance can be found by avoiding String in favour of either a ByteString or Text. In order to build the output there is a special data type called Builder
. There is a good description with examples in the [ByteString] hackage description.
The resulting code looks like this:
import Data.Monoid
display :: POSIXTime -> [(Int, Centi)] -> IO()
display t l = hPutBuilder stdout $ t_str <> space <> l_str
where
space = (byteString . pack) " "
t_str = (byteString . pack . show . timeToTimeOfDay . unsafeCoerce) $ (t `mod` posixDayLength)
l_str = foldr <> space $ map displayPair l
displayPair (a,b) = intDec a <> space <> (byteString . pack . show) b
The builder data type builds up chunks that it will then concatenate in O(1) in to a buffer for the output. Unfortunately, not all types have a builder for them and only the base types. So for outputting the others the only solution is to pack the string ... or perhaps to write a function to create a builder (and add it to the library?).