<div class="gmail_quote"><div>I&#39;d like to first say that I&#39;m very impressed with Ian&#39;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&#39;m slightly uncomfortable with the similarities between Data.Text and Data.List.  Everything works the same, until it doesn&#39;t because of a minor API change you didn&#39;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;">

&gt; I compared the API of Data.Text and Data.ByteString.Char8 and found a<br>
&gt; 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 &quot;character&quot; 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>
&gt; BS:   break :: (Char -&gt; Bool) -&gt; ByteString -&gt; (ByteString, ByteString)<br>
&gt;      breakEnd :: (Char -&gt; Bool) -&gt; ByteString -&gt; (ByteString, ByteString)<br>
&gt;      breakSubstring :: ByteString -&gt; ByteString -&gt; (ByteString, ByteString)<br>
&gt; Text: break :: Text -&gt; Text -&gt; (Text, Text)<br>
&gt;      breakEnd :: Text -&gt; Text -&gt; (Text, Text)<br>
&gt;      breakBy :: (Char -&gt; Bool) -&gt; Text -&gt; (Text, Text)<br>
&gt;<br>
&gt; BS:   count :: Char -&gt; ByteString -&gt; Int<br>
&gt; Text: count :: Text -&gt; Text -&gt; Int<br>
&gt;<br>
&gt; BS:   find :: (Char -&gt; Bool) -&gt; ByteString -&gt; Maybe Char<br>
&gt; Text: find :: Text -&gt; Text -&gt; [(Text, Text)]<br>
&gt;      findBy :: (Char -&gt; Bool) -&gt; Text -&gt; Maybe Char<br>
&gt;<br>
&gt; BS:   replicate :: Int -&gt; Char -&gt; ByteString<br>
&gt; Text: replicate :: Int -&gt; Text -&gt; Text<br>
&gt;<br>
&gt; BS:   split :: Char -&gt; ByteString -&gt; [ByteString]<br>
&gt; Text: split :: Text -&gt; Text -&gt; [Text]<br>
&gt;<br>
&gt; BS:   span :: (Char -&gt; Bool) -&gt; ByteString -&gt; (ByteString, ByteString)<br>
&gt;      spanEnd :: (Char -&gt; Bool) -&gt; ByteString -&gt; (ByteString, ByteString)<br>
&gt; Text: spanBy :: (Char -&gt; Bool) -&gt; Text -&gt; (Text, Text)<br>
&gt;<br>
&gt; BS:   splitBy :: (Char -&gt; Bool) -&gt; Text -&gt; [Text]<br>
&gt; Text: splitWith :: (Char -&gt; Bool) -&gt; ByteString -&gt; [ByteString]<br>
&gt;<br>
&gt; BS:   unfoldrN :: Int -&gt; (a -&gt; Maybe (Char, a)) -&gt; a -&gt; (ByteString, Maybe a)<br>
&gt; Text: unfoldrN :: Int -&gt; (a -&gt; Maybe (Char, a)) -&gt; a -&gt; Text<br>
&gt;<br>
&gt; BS:   zipWith :: (Char -&gt; Char -&gt; a) -&gt; ByteString -&gt; ByteString -&gt; [a]<br>
&gt; Text: zipWith :: (Char -&gt; Char -&gt; Char) -&gt; Text -&gt; Text -&gt; Text<br>
&gt;<br>
&gt; 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&#39;re handling ASCII-like protocols.<br></blockquote></div>