美好的一天。
我现在讨厌Haskell的一件事是使用字符串的数量。
首先我使用了原生的Haskell [Char]
字符串,但是当我尝试开始使用hackage库时,完全失去了无休止的转换。每个包似乎都使用不同的字符串实现,有些采用自己手工制作的东西。
接下来,我使用Data.Text
字符串和OverloadedStrings
扩展名重写了我的代码,我选择Text
,因为它有更广泛的功能,但似乎很多项目更喜欢ByteString
。
有人可以简单推理为什么要使用其中一个?
PS:顺便说一下如何从Text
转换为ByteString
?
无法匹配预期的类型 Data.ByteString.Lazy.Internal.ByteString 反对推断类型文本 预期类型:IO Data.ByteString.Lazy.Internal.ByteString 推断类型:IO文本
我从encodeUtf8
尝试Data.Text.Encoding
,但没有运气:
无法匹配预期的类型 Data.ByteString.Lazy.Internal.ByteString 针对推断类型 Data.ByteString.Internal.ByteString
UPD:
感谢您的回复,* Chunks的善良看起来像是要走的路,但我对结果感到有些震惊,我原来的功能看起来像这样:
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
之外的某个地方。
答案 0 :(得分:64)
ByteStrings
主要用于二进制数据,但如果您只需要ASCII字符集,它们也是处理文本的有效方法。如果需要处理unicode字符串,则需要使用Text
。但是,我必须强调的是,它们都不是对另一个的替代,它们通常用于不同的事情:虽然Text
代表纯粹的unicode,但你仍然需要在二进制ByteString
表示中编码和编码你,例如通过套接字或文件传输文本。
这是一篇关于unicode基础知识的好文章,它在解释unicode代码点(Text
)和编码二进制字节(ByteString
)的关系方面做得不错:{{ 3}}
您可以使用The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets模块在两种数据类型之间进行转换,或者Data.Text.Encoding如果您使用的是惰性变体(正如您根据错误消息所做的那样)。
答案 1 :(得分:26)
您肯定希望将Data.Text用于文本数据。
encodeUtf8
是要走的路。这个错误:
无法匹配预期类型Data.ByteString.Lazy.Internal.ByteString 针对推断类型Data.ByteString.Internal.ByteString
表示您正在为需要 lazy 字节字符串的代码提供 strict 字节字符串。使用fromChunks
函数轻松转换:
Data.ByteString.Lazy.fromChunks :: [Data.ByteString.Internal.ByteString] -> ByteString
所以你需要做的就是在期望lazy bytestring的地方添加函数fromChunks [myStrictByteString]
。
另一种方式的转换可以使用双重函数toChunks
完成,它使用一个惰性字节串并给出一个严格的块列表。
如果他们能够提供文本接口而不是字节串接口,或者除了字节串接口之外,您可能想要问维护者一些软件包。
答案 2 :(得分:5)
使用cs
中的单个函数Data.String.Conversions
。
它允许您在String
,ByteString
和Text
(以及ByteString.Lazy
和Text.Lazy
)之间进行转换,具体取决于输入和预期的类型。
你仍然需要打电话,但不再担心各自的类型。
有关使用示例,请参阅this answer。
答案 3 :(得分:0)
就其价值而言,我发现这两个辅助函数非常有用:
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