Common-case recommendations

String is the standard string type from Prelude, is widely used, and is rather easy to work with, as it's simply a synonym for [Char] and all list functions work with String out of the box. This representation is very convenient, but is neither fast nor memory-efficient. In addition, it doesn't fully conform to complicated Unicode rules regarding casing, string comparison, etc.

If you're working with strings a lot, you would be better off with Text from the text package, which is also very widely used in the Haskell ecosystem, has more text-specific utilities available, and is faster. If your strings are Unicode-heavy (e.g. names or addresses) and you must process them correctly, text-icu or unicode-transforms will be indispensable.

NB: Some people advocate for using Text instead of String in all cases, but if you're a beginner, String might be a better choice because all list operations apply to it. Even if you're not a beginner, you're still likely to use String in some places (when defining Show , for instance, or when working with exceptions or logging). Don't try to run away from String everywhere, sometimes it's not worth it.

Rare-case recommendations

If you need speed and you're willing to do decoding by yourself, or if you're working with network protocols, you should consider bytestring. (For some reason the networking ecosystem in Haskell mostly uses bytestring.)

If you have lots of small strings, you can switch to text-short, which has less memory overhead than Text .