vector
ifunsafeUpdate_
関数を使用して a の一部の要素を更新するときに、ストリームの融合を維持することは可能vector
ですか? 私が行ったテストでは、答えはノーのようです。以下のコードでupd
は、コアで確認されているように、関数で一時的なベクターが生成されます。
module Main where
import Data.Vector.Unboxed as U
upd :: Vector Int -> Vector Int
upd v = U.unsafeUpdate_ v (U.fromList [0]) (U.fromList [2])
sum :: Vector Int -> Int
sum = U.sum . upd
main = print $ Main.sum $ U.fromList [1..3]
コアでは、$wupd
function が使用されsum
ます - 以下に示すように、それは new を生成しますbytearray
:
$wupd :: Vector Int -> Vector Int
$wupd =
\ (w :: Vector Int) ->
case w `cast` ... of _ { Vector ipv ipv1 ipv2 ->
case main11 `cast` ... of _ { Vector ipv3 ipv4 ipv5 ->
case main7 `cast` ... of _ { Vector ipv6 ipv7 ipv8 ->
runSTRep
(\ (@ s) (s :: State# s) ->
case >=# ipv1 0 of _ {
False -> case main6 ipv1 of wild { };
True ->
case newByteArray# (*# ipv1 8) (s `cast` ...)
of _ { (# ipv9, ipv10 #) ->
case (copyByteArray# ipv2 (*# ipv 8) ipv10 0 (*# ipv1 8) ipv9)
`cast` ...
関数のコアには適切でタイトなループがありますが、sum
そのループの直前に$wupd
関数の呼び出しがあり、一時的な生成があります。
ここの例で一時的な生成を回避する方法はありますか? 私の考えでは、インデックス i のベクトルを更新することは、ストリームを解析するが、インデックス i のストリームにのみ作用し (残りはスキップ)、そこの要素を別の要素に置き換える場合です。ですから、任意の場所でベクトルを更新しても、ストリームの融合は壊れませんよね?