文本或字节串

再见。

现在我讨厌 Haskell 的一件事就是大量使用字符串的包。

首先,我使用的是原生的 Haskell[Char]字符串,但当我尝试开始使用黑客库时,却完全迷失在无穷无尽的转换中。每个包似乎都使用了不同的字符串实现,有的采用了自己手工制作的东西。

Next I rewrote my code with Data.Text strings and OverloadedStrings extension, I chose Text because it has a wider set of functions, but it seems many projects prefer ByteString.
有人可以给出简短的理由为什么使用其中之一或其他?

顺便问一下,如何从 Text转换到 ByteString

不符合预期类型 数据。字节串。懒惰。内部。字节串 对抗推断的 短信型 期望类型: IO 数据。字节串。延迟。内部。字节串 推断类型: IO 文本

我试了 Data.Text.EncodingencodeUtf8,但没有结果:

不符合预期类型 数据。字节串。懒惰。内部。字节串 根据推断类型 < em > Data. ByteString. Internal. ByteString

UPD:

Thanks for responses, that *Chunks goodness looks like way to go, but I somewhat shocked with result, my original function looked like this:

htmlToItems :: Text -> [Item]
htmlToItems =
getItems . parseTags . convertFuzzy Discard "CP1251" "UTF8"

现在变成了:

htmlToItems :: Text -> [Item]
htmlToItems =
getItems . parseTags . fromLazyBS . convertFuzzy Discard "CP1251" "UTF8" . toLazyBS
where
toLazyBS t = fromChunks [encodeUtf8 t]
fromLazyBS t = decodeUtf8 $ intercalate "" $ toChunks t

是的,这个函数没有工作,因为它是错误的,如果我们提供 Text给它,那么我们确信这个文本已经被正确编码,准备好使用和转换它是愚蠢的事情,但是这样一个冗长的转换仍然必须发生在 htmltoItems之外的某个地方。

14898 次浏览

ByteStrings主要用于二进制数据,但如果您只需要 ASCII 字符集,它们也是处理文本的有效方法。如果需要处理 unicode 字符串,则需要使用 Text。然而,我必须强调,两者都不能替代对方,而且它们通常用于不同的用途: 虽然 Text代表纯 Unicode,但无论何时,只要通过套接字或文件传输文本,仍然需要在二进制 ByteString表示之间进行编码。

这里有一篇关于 unicode 基础的好文章,它很好地解释了 unicode 码点(Text)和编码的二进制字节(ByteString) : The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets之间的关系

您可以使用 数据,文本,编码模块在两种数据类型之间进行转换,如果使用惰性变量,则使用 数据,文本,懒惰,编码(似乎是基于错误消息进行转换)。

您肯定希望将 Data.Text 用于文本数据。

encodeUtf8是正确的选择。这个错误:

无法匹配预期的类型 Data.ByteString.Lazy.Internal. ByteString against inferred type Data.ByteString.Internal.ByteString

意味着您向需要 懒惰字节串的代码提供 严格字节串。使用 fromChunks函数转换起来很容易:

Data.ByteString.Lazy.fromChunks :: [Data.ByteString.Internal.ByteString] -> ByteString

所以您需要做的就是在需要惰性字节串的地方添加函数 fromChunks [myStrictByteString]

另一种方法是使用双重函数 toChunks来完成转换,它接受一个惰性字节串并给出一个严格块列表。

You may want to ask the maintainers of some packages if they'd be able to provide a text interface instead of, or in addition to, a bytestring interface.

使用来自 Data.String.Conversions的单个函数 cs

它将允许您在 StringByteStringText(以及 ByteString.LazyText.Lazy)之间进行转换,这取决于输入和预期的类型。

您仍然需要调用它,但不再需要担心各自的类型。

有关用法示例,请参见 这个答案

值得一提的是,我发现这两个 helper 函数非常有用:

import qualified Data.ByteString.Char8 as BS
import qualified Data.Text             as T


-- | Text to ByteString
tbs :: T.Text -> BS.ByteString
tbs = BS.pack . T.unpack


-- | ByteString to Text
bst :: BS.ByteString -> T.Text
bst = T.pack . BS.unpack

例如:

foo :: [BS.ByteString]
foo = ["hello", "world"]


bar :: [T.Text]
bar = bst <$> foo


baz :: [BS.ByteString]
baz = tbs <$> bar