In my experience, it is usually a more pragmatic solution to pick the string type that is most suitable for the library's purposes, and leave conversions to the consumer.

In practice, the choice is typically between strict and lazy Text only: bytestrings do not represent strings but byte arrays, so they are not suitable for textual data; and String has atrocious performance, unless the use case is just linear character-wise traversal (and even then, lazy Texts are probably still a better choice). I would only choose String if my library were closely related to another library that has already picked String, and converting to and from Text would introduce a lot of overhead.

The downside of making your API polymorphic is that you will often find yourself having to type-annotate to disambiguate (foo . (bar :: Int -> Text) $ n), or introduce type-binding dummy functions (foo . asText . bar $ n). Another downside is that there is no canonical "StringLike" typeclass, so you either have to write your own, or pick one as a dependency. That said, there are a few libraries out there that aim to make the Haskell string situation less painful, including my own string-convert. They all differ in a few details, it mostly comes down to preference.

On Jul 14, 2016 3:00 AM, "Edward Z. Yang" <ezyang@mit.edu> wrote:
Hello KwangYul,

Supporting this sort of parametricity is one of the goals of the
Backpack project.  You can see some code that demonstrates
how this might be done: https://github.com/yihuang/tagstream-conduit/pull/18
Maybe you'll get to use this feature in GHC 8.2!

A big problem with StringLike type classes is that you must
pre-commit to the set of operations which are supported before
hand. For strings, there are many, many such operations, and it is
difficult to agree a priori what these operations should be.

Edward

Excerpts from KwangYul Seo's message of 2016-07-13 17:40:13 -0700:
> Hi all,
>
> There are multiple string types in Haskell – String, lazy/strict
> ByteString, lazy/strict Text to name a few. So to make a string handling
> function maximally reusable, it needs to support multiple string types.
>
> One approach used by TagSoup library is to make a type class StringLike
> which represents the polymorphic string type and uses it where a String
> type is normally needed. For example,
>
> parseTags :: StringLike str => str -> [Tag str]
>
> Here parseTags takes a StringLike type instead of a fixed string type.
> Users of TagSoup can pick any of String, lazy/strict ByteString,
> lazy/strict Text because they are all instances of StringLike type class.
>
> It seems StringLike type class is quite generic but it is used only in the
> TagSoup package. This makes me wonder what is the idiomatic way to support
> multiple string types in Haskell. What other approaches do we have?
>
> Thanks,
> Kwang Yul Seo
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.