Eine einfache unsafeCoerce
wird nicht funktionieren, da das Layout der Daten Konstrukteurs unterschiedlich ist:
data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e)
gegen
data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
{-# UNPACK #-} !Int -- offset
{-# UNPACK #-} !Int -- length
Sie Data.Array.Storable.Internals
und Data.ByteString.Internal
importieren können den Zugriff auf die rohen Konstrukteuren zu erhalten und dann eine der anderen konstruieren, ohne die Daten zu kopieren:
> 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))
(Ich entfernte die ziemlich lange Aufforderung von Prelude Data.Array.Storable.Internals Data.ByteString.Internal Data.ByteString>
).
Dies funktioniert nicht für Data.Vector.Unboxed
, weil hier die Daten auf dem Haskell-Heap und verwaltet von der GHC-Laufzeit, während die anderen beiden die Daten außerhalb des Haskell-Heap verwalten.
In einigen Fällen wäre es vorteilhaft, zu kopieren. Wenn Ihre Bytestrings kurze Segmente eines längeren ursprünglichen Bytezugs sind, z. ("BS.take 10 someLongByteString"), der gesamte lange Chunk wird vom 'ForeignPtr' beibehalten. In diesem Fall ist das Kopieren oft besser, da es viel weniger Speicher benötigt. Dies ist eine Art Spezialfall, aber es scheint oft zu kommen. –