<div class="gmail_quote"><div>I'd like to first say that I'm very impressed with Ian's thoroughness of review.</div><div><br></div><div>On the API differences between Data.Text and Data.ByteString.Char8, I agree with Duncan that the Data.Text API is more natural for text-oriented work, although I'm slightly uncomfortable with the similarities between Data.Text and Data.List. Everything works the same, until it doesn't because of a minor API change you didn't notice.</div>
<div><br></div><div>Would it be useful to list the API incompatibilities in the docs, either as a list or at each relevant function? Or would that just be extra noise?</div><div><br></div><div>John</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
> I compared the API of Data.Text and Data.ByteString.Char8 and found a<br>
> number of differences:<br>
<br>
Many of these are deliberate and sensible. The thing with text as<br>
opposed to lists/arrays is that almost all operations you want to do<br>
are substring based and not element based. A Unicode code point (a<br>
Char) is sadly only roughly related to the human concept of a<br>
character. In particular there are combining characters. So even if<br>
you want to search or split on a particular "character" that may mean<br>
searching for a short sequence of Chars / code points.<br>
<br>
So where the ByteString API followed the List api by being byte<br>
oriented, the Text API is substring oriented.<br>
<br>
> BS: break :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)<br>
> breakEnd :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)<br>
> breakSubstring :: ByteString -> ByteString -> (ByteString, ByteString)<br>
> Text: break :: Text -> Text -> (Text, Text)<br>
> breakEnd :: Text -> Text -> (Text, Text)<br>
> breakBy :: (Char -> Bool) -> Text -> (Text, Text)<br>
><br>
> BS: count :: Char -> ByteString -> Int<br>
> Text: count :: Text -> Text -> Int<br>
><br>
> BS: find :: (Char -> Bool) -> ByteString -> Maybe Char<br>
> Text: find :: Text -> Text -> [(Text, Text)]<br>
> findBy :: (Char -> Bool) -> Text -> Maybe Char<br>
><br>
> BS: replicate :: Int -> Char -> ByteString<br>
> Text: replicate :: Int -> Text -> Text<br>
><br>
> BS: split :: Char -> ByteString -> [ByteString]<br>
> Text: split :: Text -> Text -> [Text]<br>
><br>
> BS: span :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)<br>
> spanEnd :: (Char -> Bool) -> ByteString -> (ByteString, ByteString)<br>
> Text: spanBy :: (Char -> Bool) -> Text -> (Text, Text)<br>
><br>
> BS: splitBy :: (Char -> Bool) -> Text -> [Text]<br>
> Text: splitWith :: (Char -> Bool) -> ByteString -> [ByteString]<br>
><br>
> BS: unfoldrN :: Int -> (a -> Maybe (Char, a)) -> a -> (ByteString, Maybe a)<br>
> Text: unfoldrN :: Int -> (a -> Maybe (Char, a)) -> a -> Text<br>
><br>
> BS: zipWith :: (Char -> Char -> a) -> ByteString -> ByteString -> [a]<br>
> Text: zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text<br>
><br>
> I think the two APIs ought to be brought into agreement.<br>
<br>
Perhaps. If so, then it is the ByteString.Char8 that ought to be<br>
brought into agreement with Text, not the other way around. I think<br>
Text is right in this area. On the other hand, perhaps it makes sense<br>
for ByteString.Char8 to remain like the ByteString byte interface<br>
which is byte oriented (and probably rightly so). I hope the<br>
significance and use of ByteString.Char8 will decrease as Text becomes<br>
more popular. ByteString.Char8 is really just for the cases where<br>
you're handling ASCII-like protocols.<br></blockquote></div>