Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何在ByteString和可存储向量之间转换?_Haskell - Fatal编程技术网

Haskell 如何在ByteString和可存储向量之间转换?

Haskell 如何在ByteString和可存储向量之间转换?,haskell,Haskell,在Storable.Vector Word8和严格的ByteString之间转换的最佳方式是什么 当然,最好采用非复制(无操作)方式 我应该只unsecfect还是有一个库函数(我找不到) 此外,对于未装箱的.Vector Word8,方法是否相同?由于数据构造函数的布局不同,简单的非安全性将不起作用: data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e) vs 您可以导入Data.Array.Storable.Int

Storable.Vector Word8
和严格的
ByteString
之间转换的最佳方式是什么

当然,最好采用非复制(无操作)方式

我应该只
unsecfect
还是有一个库函数(我找不到)


此外,对于
未装箱的.Vector Word8
,方法是否相同?

由于数据构造函数的布局不同,简单的
非安全性将不起作用:

data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e)
vs

您可以导入
Data.Array.Storable.Internals
Data.ByteString.Internal
以访问原始构造函数,然后在不复制数据的情况下从另一个构造函数中构造一个:

> let bs = pack [1,2,3]
> bs
"\SOH\STX\ETX"
> let sa = case bs of (PS ptr 0 n) -> StorableArray 0 (n-1) n ptr
> :t sa
sa :: StorableArray Int GHC.Word.Word8
> Data.Array.MArray.readArray sa 1
2
> Data.Array.MArray.readArray sa 0
1
> Data.Array.MArray.readArray sa 3
*** Exception: Ix{Int}.index: Index (3) out of range ((0,2))
(我删除了相当长的
Prelude Data.Array.Storable.Internal Data.ByteString.Internal Data.ByteString>
提示)

这不适用于
Data.Vector.unbox
,因为这里的数据位于Haskell堆上,由GHC运行时管理,而其他两个则在Haskell堆之外管理数据

byteStringToVector :: (Storable a) => BS.ByteString -> V.Vector a
byteStringToVector bs = vec where
    vec = V.unsafeFromForeignPtr (castForeignPtr fptr) (scale off) (scale len)
    (fptr, off, len) = BS.toForeignPtr bs
    scale = (`div` sizeOfElem vec)

sizeOfElem vec = sizeOf (undefined `asTypeOf` V.head vec)

在某些情况下,复制会有好处。如果您的bytestring是较长原始bytestring的短段,例如(
BS.take 10 someLongByteString
),则整个长块将由
ForeignPtr
保留。在这种情况下,复制通常更好,因为它将使用更少的内存。这是一种特殊的情况,但似乎经常出现。谢谢你把它放在Hackage上!
byteStringToVector :: (Storable a) => BS.ByteString -> V.Vector a
byteStringToVector bs = vec where
    vec = V.unsafeFromForeignPtr (castForeignPtr fptr) (scale off) (scale len)
    (fptr, off, len) = BS.toForeignPtr bs
    scale = (`div` sizeOfElem vec)

sizeOfElem vec = sizeOf (undefined `asTypeOf` V.head vec)