Ответ 1
Простой unsafeCoerce
не будет работать, поскольку компоновка конструкторов данных отличается:
data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e)
против.
data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
{-# UNPACK #-} !Int -- offset
{-# UNPACK #-} !Int -- length
Вы можете импортировать 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.Internals Data.ByteString.Internal Data.ByteString>
).
Это не будет работать для Data.Vector.Unboxed
, потому что здесь данные находятся в куче Haskell и управляются средой выполнения GHC, в то время как другие два управляют данными вне кучи Haskell.