Skip to content

Commit f672ad6

Browse files
committed
Correctly implement fromArray for strict vector
fromArray reduces all elements of array to WHNF but that changes complexity from O(1) to O(n). To compensate we provide lazy variant which pass all responsibility to user
1 parent 06b6cf6 commit f672ad6

File tree

1 file changed

+42
-9
lines changed

1 file changed

+42
-9
lines changed

vector/src/Data/Vector/Strict.hs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{-# LANGUAGE TypeFamilies #-}
88

99
-- |
10-
-- Module : Data.Vector
10+
-- Module : Data.Vector.Strict
1111
-- Copyright : (c) Roman Leshchinskiy 2008-2010
1212
-- Alexey Kuleshevich 2020-2022
1313
-- Aleksey Khudyakov 2020-2022
@@ -166,7 +166,7 @@ module Data.Vector.Strict (
166166
toList, Data.Vector.Strict.fromList, Data.Vector.Strict.fromListN,
167167

168168
-- ** Arrays
169-
toArray, fromArray, toArraySlice, unsafeFromArraySlice,
169+
toArray, fromArray, lazyFromArray, toArraySlice, unsafeFromArraySlice, unsafeLazyFromArraySlice,
170170

171171
-- ** Other vector types
172172
G.convert,
@@ -2196,12 +2196,23 @@ fromListN = G.fromListN
21962196
-- Conversions - Arrays
21972197
-- -----------------------------
21982198

2199-
-- | /O(1)/ Convert an array to a vector.
2199+
-- | /O(n)/ Convert an array to a vector and reduce each element to WHNF.
22002200
--
2201-
-- @since 0.12.2.0
2201+
-- @since NEXT
22022202
fromArray :: Array a -> Vector a
22032203
{-# INLINE fromArray #-}
2204-
fromArray arr = Vector 0 (sizeofArray arr) arr
2204+
fromArray arr = liftRnfV (`seq` ()) vec `seq` vec
2205+
where
2206+
vec = lazyFromArray arr
2207+
2208+
-- | /O(1)/ Convert an array to a vector. This function does not touch
2209+
-- content of array so resulting vector may contain bottoms.
2210+
--
2211+
-- @since NEXT
2212+
lazyFromArray :: Array a -> Vector a
2213+
{-# INLINE lazyFromArray #-}
2214+
lazyFromArray arr = Vector 0 (sizeofArray arr) arr
2215+
22052216

22062217
-- | /O(n)/ Convert a vector to an array.
22072218
--
@@ -2224,9 +2235,11 @@ toArraySlice :: Vector a -> (Array a, Int, Int)
22242235
toArraySlice (Vector offset len arr) = (arr, offset, len)
22252236

22262237

2227-
-- | /O(1)/ Convert an array slice to a vector. This function is very unsafe,
2228-
-- because constructing an invalid vector can yield almost all other safe
2229-
-- functions in this module unsafe. These are equivalent:
2238+
-- | /O(n)/ Convert an array slice to a vector and reduce each element to WHNF.
2239+
--
2240+
-- This function is very unsafe, because constructing an invalid
2241+
-- vector can yield almost all other safe functions in this module
2242+
-- unsafe. These are equivalent:
22302243
--
22312244
-- > unsafeFromArraySlice len offset === unsafeTake len . unsafeDrop offset . fromArray
22322245
--
@@ -2237,7 +2250,27 @@ unsafeFromArraySlice ::
22372250
-> Int -- ^ Length
22382251
-> Vector a
22392252
{-# INLINE unsafeFromArraySlice #-}
2240-
unsafeFromArraySlice arr offset len = Vector offset len arr
2253+
unsafeFromArraySlice arr offset len = liftRnfV (`seq` ()) vec `seq` vec
2254+
where vec = unsafeLazyFromArraySlice arr offset len
2255+
2256+
-- | /O(1)/ Convert an array slice to a vector. This function does not touch
2257+
-- content of array so resulting vector may contain bottoms.
2258+
--
2259+
-- This function is very unsafe, because constructing an invalid
2260+
-- vector can yield almost all other safe functions in this module
2261+
-- unsafe. These are equivalent:
2262+
--
2263+
-- > unsafeFromArraySlice len offset === unsafeTake len . unsafeDrop offset . fromArray
2264+
--
2265+
-- @since 0.13.0.0
2266+
unsafeLazyFromArraySlice ::
2267+
Array a -- ^ Immutable boxed array.
2268+
-> Int -- ^ Offset
2269+
-> Int -- ^ Length
2270+
-> Vector a
2271+
{-# INLINE unsafeLazyFromArraySlice #-}
2272+
unsafeLazyFromArraySlice arr offset len = Vector offset len arr
2273+
22412274

22422275
-- Conversions - Mutable vectors
22432276
-- -----------------------------

0 commit comments

Comments
 (0)