Skip to content

Commit da90e33

Browse files
committed
Strict boxed: Add Unsafe modules
1 parent 0f08f5c commit da90e33

File tree

6 files changed

+422
-351
lines changed

6 files changed

+422
-351
lines changed

vector/src/Data/Vector/Strict.hs

Lines changed: 8 additions & 272 deletions
Original file line numberDiff line numberDiff line change
@@ -178,220 +178,17 @@ module Data.Vector.Strict (
178178
) where
179179

180180
import Control.Applicative (Applicative)
181-
import Data.Coerce
182-
import Data.Vector.Strict.Mutable ( MVector(..) )
183-
import Data.Primitive.Array
181+
import Control.Monad.Primitive
182+
import Data.Vector.Strict.Mutable.Unsafe ( MVector(..) )
183+
import Data.Vector.Strict.Unsafe
184184
import qualified Data.Vector.Generic as G
185-
import qualified Data.Vector as V
186-
187-
import Control.DeepSeq ( NFData(rnf), NFData1(liftRnf))
185+
import qualified Data.Traversable as Traversable
188186

189-
import Control.Monad ( MonadPlus(..), ap )
190-
import Control.Monad.ST ( ST, runST )
191-
import Control.Monad.Primitive
192-
import qualified Control.Monad.Fail as Fail
193-
import Control.Monad.Fix ( MonadFix (mfix) )
194-
import Control.Monad.Zip
195-
import Data.Function ( fix )
187+
import Control.Monad.ST ( ST )
196188

197189
import Prelude
198-
( Eq(..), Ord(..), Num, Enum, Monoid, Functor, Monad, Show, Bool, Ordering(..), Int, Maybe, Either
199-
, return, showsPrec, fmap, otherwise, id, flip, const
200-
, (>>=), (+), (-), (.), ($), seq)
201-
202-
import Data.Functor.Classes (Eq1 (..), Ord1 (..), Read1 (..), Show1 (..))
203-
import Data.Data ( Data(..) )
204-
import Text.Read ( Read(..), readListPrecDefault )
205-
import Data.Semigroup ( Semigroup(..) )
206-
207-
import qualified Control.Applicative as Applicative
208-
import qualified Data.Foldable as Foldable
209-
import qualified Data.Traversable as Traversable
210-
211-
import qualified GHC.Exts as Exts (IsList(..))
212-
213-
214-
-- | Strict boxed vectors, supporting efficient slicing.
215-
newtype Vector a = Vector (V.Vector a)
216-
deriving (Foldable.Foldable, Semigroup, Monoid)
217-
218-
-- NOTE: [GND for strict vector]
219-
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
220-
--
221-
-- Strict boxed vectors (both mutable an immutable) are newtypes over
222-
-- lazy ones. This makes it possible to use GND to derive instances.
223-
-- However one must take care to preserve strictness since Vector
224-
-- instance for lazy vectors would be used.
225-
--
226-
-- In general it's OK to derive instances where vectors are passed as
227-
-- parameters (e.g. Eq, Ord) and not OK to derive ones where new
228-
-- vector is created (e.g. Read, Functor)
229-
230-
instance NFData a => NFData (Vector a) where
231-
rnf = liftRnf rnf
232-
{-# INLINEABLE rnf #-}
233-
234-
-- | @since 0.13.2.0
235-
instance NFData1 Vector where
236-
liftRnf elemRnf = foldl' (\_ -> elemRnf) ()
237-
{-# INLINEABLE liftRnf #-}
238-
239-
instance Show a => Show (Vector a) where
240-
showsPrec = G.showsPrec
241-
242-
instance Read a => Read (Vector a) where
243-
readPrec = G.readPrec
244-
readListPrec = readListPrecDefault
245-
246-
instance Show1 Vector where
247-
liftShowsPrec = G.liftShowsPrec
248-
249-
instance Read1 Vector where
250-
liftReadsPrec = G.liftReadsPrec
251-
252-
instance Exts.IsList (Vector a) where
253-
type Item (Vector a) = a
254-
fromList = Data.Vector.Strict.fromList
255-
fromListN = Data.Vector.Strict.fromListN
256-
toList = toList
257-
258-
instance Data a => Data (Vector a) where
259-
gfoldl = G.gfoldl
260-
toConstr _ = G.mkVecConstr "Data.Vector.Strict.Vector"
261-
gunfold = G.gunfold
262-
dataTypeOf _ = G.mkVecType "Data.Vector.Strict.Vector"
263-
dataCast1 = G.dataCast
264-
265-
type instance G.Mutable Vector = MVector
266-
267-
instance G.Vector Vector a where
268-
{-# INLINE basicUnsafeFreeze #-}
269-
basicUnsafeFreeze = coerce (G.basicUnsafeFreeze @V.Vector @a)
270-
{-# INLINE basicUnsafeThaw #-}
271-
basicUnsafeThaw = coerce (G.basicUnsafeThaw @V.Vector @a)
272-
{-# INLINE basicLength #-}
273-
basicLength = coerce (G.basicLength @V.Vector @a)
274-
{-# INLINE basicUnsafeSlice #-}
275-
basicUnsafeSlice = coerce (G.basicUnsafeSlice @V.Vector @a)
276-
{-# INLINE basicUnsafeIndexM #-}
277-
basicUnsafeIndexM = coerce (G.basicUnsafeIndexM @V.Vector @a)
278-
{-# INLINE basicUnsafeCopy #-}
279-
basicUnsafeCopy = coerce (G.basicUnsafeCopy @V.Vector @a)
280-
{-# INLINE elemseq #-}
281-
elemseq _ = seq
282-
283-
-- See NOTE: [GND for strict vector]
284-
--
285-
-- Deriving strategies are only available since 8.2. So we can't use
286-
-- deriving newtype until we drop support for 8.0
287-
instance Eq a => Eq (Vector a) where
288-
{-# INLINE (==) #-}
289-
(==) = coerce ((==) @(V.Vector a))
290-
291-
-- See NOTE: [GND for strict vector]
292-
instance Ord a => Ord (Vector a) where
293-
{-# INLINE compare #-}
294-
compare = coerce (compare @(V.Vector a))
295-
{-# INLINE (<) #-}
296-
(<) = coerce ((<) @(V.Vector a))
297-
{-# INLINE (<=) #-}
298-
(<=) = coerce ((<=) @(V.Vector a))
299-
{-# INLINE (>) #-}
300-
(>) = coerce ((>) @(V.Vector a))
301-
{-# INLINE (>=) #-}
302-
(>=) = coerce ((>=) @(V.Vector a))
303-
304-
instance Eq1 Vector where
305-
{-# INLINE liftEq #-}
306-
liftEq = eqBy
307-
308-
instance Ord1 Vector where
309-
{-# INLINE liftCompare #-}
310-
liftCompare = cmpBy
311-
312-
instance Functor Vector where
313-
{-# INLINE fmap #-}
314-
fmap = map
315-
316-
{-# INLINE (<$) #-}
317-
(<$) = map . const
318-
319-
instance Monad Vector where
320-
{-# INLINE return #-}
321-
return = Applicative.pure
322-
323-
{-# INLINE (>>=) #-}
324-
(>>=) = flip concatMap
325-
326-
-- | @since 0.13.2.0
327-
instance Fail.MonadFail Vector where
328-
{-# INLINE fail #-}
329-
fail _ = empty
330-
331-
instance MonadPlus Vector where
332-
{-# INLINE mzero #-}
333-
mzero = empty
334-
335-
{-# INLINE mplus #-}
336-
mplus = (++)
337-
338-
instance MonadZip Vector where
339-
{-# INLINE mzip #-}
340-
mzip = zip
341-
342-
{-# INLINE mzipWith #-}
343-
mzipWith = zipWith
344-
345-
{-# INLINE munzip #-}
346-
munzip = unzip
347-
348-
-- | This instance has the same semantics as the one for lists.
349-
--
350-
-- @since 0.13.2.0
351-
instance MonadFix Vector where
352-
-- We take care to dispose of v0 as soon as possible (see headM docs).
353-
--
354-
-- It's perfectly safe to use non-monadic indexing within generate
355-
-- call since intermediate vector won't be created until result's
356-
-- value is demanded.
357-
{-# INLINE mfix #-}
358-
mfix f
359-
| null v0 = empty
360-
-- We take first element of resulting vector from v0 and create
361-
-- rest using generate. Note that cons should fuse with generate
362-
| otherwise = runST $ do
363-
h <- headM v0
364-
return $ cons h $
365-
generate (lv0 - 1) $
366-
\i -> fix (\a -> f a ! (i + 1))
367-
where
368-
-- Used to calculate size of resulting vector
369-
v0 = fix (f . head)
370-
!lv0 = length v0
371-
372-
instance Applicative.Applicative Vector where
373-
{-# INLINE pure #-}
374-
pure = singleton
375-
376-
{-# INLINE (<*>) #-}
377-
(<*>) = ap
378-
379-
instance Applicative.Alternative Vector where
380-
{-# INLINE empty #-}
381-
empty = empty
382-
383-
{-# INLINE (<|>) #-}
384-
(<|>) = (++)
385-
386-
instance Traversable.Traversable Vector where
387-
{-# INLINE traverse #-}
388-
traverse = traverse
389-
390-
{-# INLINE mapM #-}
391-
mapM = mapM
392-
393-
{-# INLINE sequence #-}
394-
sequence = sequence
190+
( Eq(..), Ord(..), Num, Enum, Monoid, Monad, Bool, Ordering(..), Int, Maybe, Either
191+
, id)
395192

396193
-- Length information
397194
-- ------------------
@@ -2549,67 +2346,6 @@ iforA_ :: (Applicative f)
25492346
iforA_ = G.iforA_
25502347

25512348

2552-
-- Conversions - Lazy vectors
2553-
-- -----------------------------
2554-
2555-
-- | /O(1)/ Convert strict array to lazy array
2556-
toLazy :: Vector a -> V.Vector a
2557-
toLazy (Vector v) = v
2558-
2559-
-- | /O(n)/ Convert lazy array to strict array. This function reduces
2560-
-- each element of vector to WHNF.
2561-
fromLazy :: V.Vector a -> Vector a
2562-
fromLazy vec = liftRnf (`seq` ()) v `seq` v where v = Vector vec
2563-
2564-
2565-
-- Conversions - Arrays
2566-
-- -----------------------------
2567-
2568-
-- | /O(n)/ Convert an array to a vector and reduce each element to WHNF.
2569-
--
2570-
-- @since 0.13.2.0
2571-
fromArray :: Array a -> Vector a
2572-
{-# INLINE fromArray #-}
2573-
fromArray arr = liftRnf (`seq` ()) vec `seq` vec
2574-
where
2575-
vec = Vector $ V.fromArray arr
2576-
2577-
-- | /O(n)/ Convert a vector to an array.
2578-
--
2579-
-- @since 0.13.2.0
2580-
toArray :: Vector a -> Array a
2581-
{-# INLINE toArray #-}
2582-
toArray (Vector v) = V.toArray v
2583-
2584-
-- | /O(1)/ Extract the underlying `Array`, offset where vector starts and the
2585-
-- total number of elements in the vector. Below property always holds:
2586-
--
2587-
-- > let (array, offset, len) = toArraySlice v
2588-
-- > v === unsafeFromArraySlice len offset array
2589-
--
2590-
-- @since 0.13.2.0
2591-
toArraySlice :: Vector a -> (Array a, Int, Int)
2592-
{-# INLINE toArraySlice #-}
2593-
toArraySlice (Vector v) = V.toArraySlice v
2594-
2595-
2596-
-- | /O(n)/ Convert an array slice to a vector and reduce each element to WHNF.
2597-
--
2598-
-- This function is very unsafe, because constructing an invalid
2599-
-- vector can yield almost all other safe functions in this module
2600-
-- unsafe. These are equivalent:
2601-
--
2602-
-- > unsafeFromArraySlice len offset === unsafeTake len . unsafeDrop offset . fromArray
2603-
--
2604-
-- @since 0.13.2.0
2605-
unsafeFromArraySlice ::
2606-
Array a -- ^ Immutable boxed array.
2607-
-> Int -- ^ Offset
2608-
-> Int -- ^ Length
2609-
-> Vector a
2610-
{-# INLINE unsafeFromArraySlice #-}
2611-
unsafeFromArraySlice arr offset len = liftRnf (`seq` ()) vec `seq` vec
2612-
where vec = Vector (V.unsafeFromArraySlice arr offset len)
26132349

26142350

26152351

@@ -2687,4 +2423,4 @@ copy = G.copy
26872423

26882424
-- $setup
26892425
-- >>> :set -Wno-type-defaults
2690-
-- >>> import Prelude (Char, String, Bool(True, False), min, max, fst, even, undefined, Ord(..))
2426+
-- >>> import Prelude (Char, String, Bool(..), min, max, fst, even, undefined, Ord(..), (<>), Num(..),($))

0 commit comments

Comments
 (0)