Lazy.ByteString和Lazy.Char8.ByteString之间的区别

3

我对《Real World Haskell》中的代码有些困惑。


import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.ByteString.Lazy as L

matchHeader :: L.ByteString -> L.ByteString -> Maybe L.ByteString
matchHeader prefix str
    | prefix `L8.isPrefixOf` str
        = Just (L8.dropWhile isSpace (L.drop (L.length prefix) str))
    | otherwise
        = Nothing

在这个函数中,LL8似乎可以互换使用,如果我用L8替换L,特别是对于类型L.ByteStringL8.ByteString,就能编译通过。我在hackage上看到它们链接到了同一个源,这是否意味着Data.ByteString.Lazy.Char8.ByteStringData.ByteString.Lazy.ByteString是相同的?为什么这里使用L8.isPrefixOf而不是L.isPrefixOf


我最初对此有些困惑,因此我在FPComplete上写了一篇关于ByteString的教程(https://www.fpcomplete.com/user/tekul/bytestring-bits-and-pieces),您可能会发现它很有用。主要是关于非惰性bytestrings,但是`Word8`和`Char`版本之间的差异是相同的。 - Shaun the Sheep
2个回答

4

很有趣,我使用了所有的ByteStrings但从未注意到(直到你提到)Char8和Word8版本是内部相同的数据类型。

一旦提到,我就必须去看代码……Data/ByteString/Lazy/Char8.hs中的以下行显示不仅数据类型相同,而且许多函数也以相同方式重新导出。

-- Functions transparently exported
import Data.ByteString.Lazy 
        (fromChunks, toChunks, fromStrict, toStrict
        ,empty,null,length,tail,init,append,reverse,transpose,cycle
        ,concat,take,drop,splitAt,intercalate,isPrefixOf,group,inits,tails,copy
        ,hGetContents, hGet, hPut, getContents
        ,hGetNonBlocking, hPutNonBlocking
        ,putStr, hPutStr, interact)

看起来大部分 Data.ByteString.(Lazy.)?Char8 只是一个方便地包装在 Data.ByteString(.Lazy)? 周围。这也为我解释了为什么 show 对 Word8 ByteStrings 一直会创建字符串输出。

当然,有些东西是不同的,比如你尝试创建一个 ByteString 时就会发现-

B.pack "abcd"  -- This fails
B.pack [65, 66, 67, 68] -- output is "ABCD"
B8.pack "abcd"  -- This works

4
根据文档Lazy.ByteStringLazy.Char.ByteString都是Word8向量的高效表示形式,支持许多高效操作。因此,在内部它们似乎是相同的,可以互换使用。
但是,Lazy.Char.ByteString还具有以下特点:
  • 所有字符将被截断为8位(所以要小心!)
  • Char8界面提供了ByteString类型的IsString实例,使您能够使用字符串字面量,并将它们隐式地打包到ByteStrings中。(应启用OverloadedStrings扩展来实现这一点)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接