In other words, here's what I think the three different benchmarks are really doing:
* String: generates a list of Strings, passes each String to a relatively inefficient IO routine.
* ByteString: encodes Strings one by one into ByteStrings, generates a list of these ByteStrings, and passes each ByteString to a very efficient IO routine.
: Text: encodes Strings one by one into Texts, generates a list of these Texts, calls a UTF-8 decoding function to decode each Text into a ByteString, and passes each resulting ByteString to a very efficient IO routine.