Một đơn giản unsafeCoerce
sẽ không hoạt động, như cách bố trí của các nhà thầu dữ liệu là khác nhau:
data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e)
vs
data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
{-# UNPACK #-} !Int -- offset
{-# UNPACK #-} !Int -- length
Bạn có thể nhập Data.Array.Storable.Internals
và Data.ByteString.Internal
để có được quyền truy cập vào các nhà thầu liệu và sau đó xây dựng một cái khác mà không sao chép dữ liệu:
> 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))
(Tôi đã xóa lời nhắc khá dài là Prelude Data.Array.Storable.Internals Data.ByteString.Internal Data.ByteString>
).
Điều này sẽ không hoạt động cho Data.Vector.Unboxed
, bởi vì ở đây dữ liệu nằm trên vùng Haskell và được quản lý bởi thời gian chạy GHC, trong khi hai dữ liệu kia quản lý dữ liệu bên ngoài vùng Haskell.
Nguồn
2013-09-08 17:12:44
Trong một số trường hợp nó sẽ có lợi để sao chép. Nếu các phần tử thuở của bạn là các đoạn ngắn của bản gốc dài hơn, ví dụ: ('BS.take 10 someLongByteString'), toàn bộ đoạn dài sẽ được giữ lại bởi' ForeignPtr'. Trong trường hợp này sao chép thường tốt hơn vì nó sẽ sử dụng ít bộ nhớ hơn nhiều. Đây là một trường hợp đặc biệt, nhưng dường như nó xuất hiện thường xuyên. –