Haskell中ByteString和ByteString.Lazy的常用函数

时间:2014-02-06 08:26:11

标签: haskell

我实现了读取ByteString并以十六进制格式转换它的函数。 例如。给定“AA10”,它将其转换为[170,16]

import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Internal as BS (w2c)

rHex :: BSL.ByteString -> BSL.ByteString
rHex bs
    | BSL.null bs = BSL.empty
    | BSL.null rest' = fromHex c1 `BSL.cons` BSL.empty
    | otherwise = rChunk c1 c2 `BSL.cons` rHex rest
          where (c1, rest') = (BSL.head bs, BSL.tail bs)
                (c2, rest) = (BSL.head rest', BSL.tail rest')
                rChunk c1 c2 = (fromHex c1) * 16 + fromHex c2
fromHex = fromIntegral . digitToInt . BS.w2c

但是我意识到我需要相同的功能但是对于简单的ByteString,而不是Lazy。 我遇到的唯一方法就是这样:

import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BS (w2c)

rHex' funcs@(null, empty, cons, head, tail, fromHex) bs
    | null bs = empty
    | null rest' = fromHex c1 `cons` empty
    | otherwise = rChunk c1 c2 `cons` rHex' funcs rest
          where (c1, rest') = (head bs, tail bs)
                (c2, rest) = (head rest', tail rest')
                rChunk c1 c2 = (fromHex c1) * 16 + fromHex c2

fromHex = fromIntegral . digitToInt . BS.w2c

rHexBSL :: BSL.ByteString -> BSL.ByteString
rHexBSL = rHex' (BSL.null, BSL.empty, BSL.cons, BSL.head, BSL.tail, fromHex)

rHexBS :: BS.ByteString -> BS.ByteString
rHexBS = rHex' (BS.null, BS.empty, BS.cons, BS.head, BS.tail, fromHex)

所以我直接在函数rHex' rHexBSL的{​​{1}}中传递了所有需要的函数。 是否有更多的Haskell方法为Bytestring和Bytestring.Lazy创建一个通用函数? 也许创建类型类或什么?

3 个答案:

答案 0 :(得分:3)

您始终可以使用toStrict中的fromStrictData.ByteString.Lazy函数在严格和惰性类型之间来回转换。在这种特殊情况下:

rHexBS = BSL.toStrict . hHexBSL . BSL.fromStrict

答案 1 :(得分:3)

我会通过使用[Word8]并使用packunpack为每种类型的ByteString获取您想要的内容来简化此操作 - 例如:

toHex :: Word8 -> Word8 -> Word8
toHex a b = (fromHex a) * 16 + fromHex b

hexify :: [Word8] -> [Word8] -> [Word8]
hexify (a:b:cs) = toHex a b : hexify cs
hexify [b]      = toHex 0 b
hexify []       = []

rHexBSL :: BSL.ByteString -> BSL.ByteString
rHexBSL = BSL.pack . hexify . BSL.unpack

rHexBS :: BS.ByteString -> BS.ByteString
rHexBS = BS.pack . hexify . BS.unpack

我认为这样做很有可能实现融合,使运营更有效率。

也就是说,看看布莱恩是如何在他的base16-bytestring` package中做到的。

答案 2 :(得分:0)

有一个类可以交给镜头包http://hackage.haskell.org/package/lens-4.0.1/docs/Data-ByteString-Lens.html#v:packedBytes。所以给了user5402的代码 对于hexify,我想应该是

 hexify :: [Word8] -> [Word8]
 hexify (a:b:cs) = toHex a b : hexify cs
 hexify [b]      = [toHex 0 b]
 hexify []       = []

你会发现(在范围内也有Control.Lens.under)你可以写

 rHex :: IsByteString b => b -> b 
 rHex = under packedBytes hexify

并做其他各种事情。它可能比它的价值更麻烦;我提到它是因为有一个合适的班级。 under packedBytes f只是对繁琐的pack . f . unpack业务进行了编码,但涵盖了pack的两种感官。