Haskell Bytestring到[Word16]的高效转换

Haskell Bytestring到[Word16]的高效转换,haskell,bytestring,Haskell,Bytestring,我正在尝试从bytestring到Word16列表的简单转换。下面使用Data.Binary.Get的实现是可行的,尽管这是代码中的一个性能瓶颈。这是可以理解的,因为IO总是很慢,但我想知道是否有更有效的方法来做到这一点 getImageData' = do e <- isEmpty if e then return [] else do w <- getWord16be ws <- getImageData' r

我正在尝试从bytestring到Word16列表的简单转换。下面使用Data.Binary.Get的实现是可行的,尽管这是代码中的一个性能瓶颈。这是可以理解的,因为IO总是很慢,但我想知道是否有更有效的方法来做到这一点

getImageData' = do
    e <- isEmpty
    if e then return []
      else do
      w <- getWord16be
      ws <- getImageData'
      return $ w : ws
getImageData'=do

e我怀疑您在使用
Data.Binary.Get
时遇到的最大问题是,解码器对于您的目的来说本质上太严格了。
serialise
和其他序列化库似乎也是如此。我认为最根本的问题是,尽管您知道只要
ByteString
的字节数为偶数,操作就会成功,但库并不知道这一点。因此,它必须通过testring阅读整个
,然后才能得出“啊,是的,一切都很好”的结论,并构建您所请求的列表。事实上,按照构建结果的方式,它将在实际执行任何有用的操作之前构建大量闭包(数量与长度成比例)

你怎么能解决这个问题?直接使用
bytestring
库即可。最简单的方法是使用
解包
,但我认为您可能会获得更好的性能,如下所示:

{-# language BangPatterns #-}
module Wordy where
import qualified Data.ByteString as BS
import Data.ByteString (ByteString)
import Data.Word (Word16)
import Data.Maybe (fromMaybe)
import Data.Bits (unsafeShiftL)

toDBs :: ByteString -> Maybe [Word16]
toDBs bs0
  | odd (BS.length bs0) = Nothing
  | otherwise = Just (go bs0)
  where
    go bs = fromMaybe [] $ do
      (b1, bs') <- BS.uncons bs
      (b2, bs'') <- BS.uncons bs'
      let !res = (fromIntegral b1 `unsafeShiftL` 8) + fromIntegral b2
      Just (res : go bs'')
{-#语言模式}
模块Wordy在哪里
将符合条件的数据.ByteString作为BS导入
导入Data.ByteString(ByteString)
导入数据.Word(Word16)
导入数据。可能(来自可能)
导入数据位(unsafeShiftL)
toDBs::ByteString->Maybe[Word16]
toDBs bs0
|奇数(BS.length bs0)=无
|否则=仅(转到bs0)
哪里
go bs=fromMaybe[]$do

(b1,bs')这里没有IO。反序列化和它的性能是我对Haskell最初的烦恼之一。您可以在pureMD5包和word32反序列化中查找一种方法。