How to support multiple string types in Haskell?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

How to support multiple string types in Haskell?

KwangYul Seo
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.
Reply | Threaded
Open this post in threaded view
|

Re: How to support multiple string types in Haskell?

Edward Z. Yang
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.
Reply | Threaded
Open this post in threaded view
|

Re: How to support multiple string types in Haskell?

Tobias Dammers

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" <[hidden email]> 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.

_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: How to support multiple string types in Haskell?

Mario Blažević
In reply to this post by KwangYul Seo

On Wed, Jul 13, 2016 at 8:40 PM, KwangYul Seo <[hidden email]> wrote:
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.

...
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?

 
StringLike is only one of the packages supplying the class or classes to support all the usual string types. There is also ListLike and (my own) monoid-subclasses. You can visit
http://packdeps.haskellers.com/reverse to see all their reverse dependencies and see how they're used.


_______________________________________________
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.