1
- {-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples #-}
1
+ {-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples, ScopedTypeVariables #-}
2
2
{-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
3
3
4
4
-- | Zero based arrays.
@@ -57,8 +57,9 @@ import Control.Applicative (Applicative (..), (<$>))
57
57
#endif
58
58
import Control.Applicative (liftA2 )
59
59
import Control.DeepSeq
60
- import GHC.Exts (Int (.. ), Int #, reallyUnsafePtrEquality #, tagToEnum #, unsafeCoerce #, State #)
60
+ import GHC.Exts (Int (.. ), Int #, reallyUnsafePtrEquality #, tagToEnum #, unsafeCoerce #, State #, (+#) )
61
61
import GHC.ST (ST (.. ))
62
+ import Control.Monad.ST (stToIO )
62
63
63
64
#if __GLASGOW_HASKELL__ >= 709
64
65
import Prelude hiding (filter , foldr , length , map , read , traverse )
@@ -475,49 +476,36 @@ fromList n xs0 =
475
476
toList :: Array a -> [a ]
476
477
toList = foldr (:) []
477
478
478
- data SList a = SCons ! a ( SList a ) | SNil
479
+ newtype STA a = STA { _runSTA :: forall s . MutableArray # s a -> ST s ( Array a )}
479
480
480
- traverseToSList
481
- :: Applicative f
482
- => (a -> f b ) -> [a ] -> f (SList b )
483
- traverseToSList f = go
484
- where
485
- go (a : as) = liftA2 SCons (f a) (go as)
486
- go [] = pure SNil
487
-
488
- _slength :: SList a -> Int
489
- _slength = go 0 where
490
- go ! acc SNil = acc
491
- go acc (SCons _ xs) = go (acc + 1 ) xs
481
+ runSTA :: Int -> STA a -> Array a
482
+ runSTA ! n (STA m) = runST $ new_ n >>= \ (MArray ar) -> m ar
492
483
493
- fromSList :: Int -> SList a -> Array a
494
- fromSList n xs0 =
495
- CHECK_EQ (" fromSList" , n, _slength xs0)
496
- run $ do
497
- mary <- new_ n
498
- go xs0 mary 0
484
+ traverse :: forall f a b . Applicative f => (a -> f b ) -> Array a -> f (Array b )
485
+ traverse f = \ ! ary -> runSTA (length ary) <$> foldr go stop ary 0 #
499
486
where
500
- go SNil ! mary ! _ = return mary
501
- go (SCons x xs) mary i = do write mary i x
502
- go xs mary (i + 1 )
503
-
504
- traverse :: Applicative f => (a -> f b ) -> Array a -> f (Array b )
505
- traverse f = \ ary -> fromList (length ary) `fmap`
506
- Traversable. traverse f (toList ary)
487
+ go :: a -> (Int # -> f (STA b )) -> Int # -> f (STA b )
488
+ go a r i = liftA2 (\ b (STA m) -> STA $ \ mry# -> write (MArray mry# ) (I # i) b >> m mry# ) (f a) (r (i +# 1 # ))
489
+ stop :: Int # -> f (STA b )
490
+ stop _i = pure (STA (\ mry# -> unsafeFreeze (MArray mry# )))
507
491
{-# INLINE [1] traverse #-}
508
492
509
- traverse' :: Applicative f => (a -> f b ) -> Array a -> f (Array b )
510
- traverse' f = \ ary -> fromSList (length ary) `fmap`
511
- traverseToSList f (toList ary)
493
+ traverse' :: forall f a b . Applicative f => (a -> f b ) -> Array a -> f (Array b )
494
+ traverse' f = \ ! ary -> runSTA (length ary) <$> foldr go stop ary 0 #
495
+ where
496
+ go :: a -> (Int # -> f (STA b )) -> Int # -> f (STA b )
497
+ go a r i = liftA2 (\ ! b (STA m) -> STA $ \ mry# -> write (MArray mry# ) (I # i) b >> m mry# ) (f a) (r (i +# 1 # ))
498
+ stop :: Int # -> f (STA b )
499
+ stop _i = pure (STA (\ mry# -> unsafeFreeze (MArray mry# )))
512
500
{-# INLINE [1] traverse' #-}
513
501
514
- -- Traversing in ST, we don't need to make a list ; we
502
+ -- Traversing in ST, we don't need to get fancy ; we
515
503
-- can just do it directly.
516
504
traverseST :: (a -> ST s b ) -> Array a -> ST s (Array b )
517
505
traverseST f = \ ary0 ->
518
506
let
519
507
! len = length ary0
520
- go k mary
508
+ go k ! mary
521
509
| k == len = return mary
522
510
| otherwise = do
523
511
x <- indexM ary0 k
@@ -527,17 +515,33 @@ traverseST f = \ ary0 ->
527
515
in new_ len >>= (go 0 >=> unsafeFreeze)
528
516
{-# INLINE traverseST #-}
529
517
518
+ traverseIO :: (a -> IO b ) -> Array a -> IO (Array b )
519
+ traverseIO f = \ ary0 ->
520
+ let
521
+ ! len = length ary0
522
+ go k ! mary
523
+ | k == len = return mary
524
+ | otherwise = do
525
+ x <- stToIO $ indexM ary0 k
526
+ y <- f x
527
+ stToIO $ write mary k y
528
+ go (k + 1 ) mary
529
+ in stToIO (new_ len) >>= (go 0 >=> stToIO . unsafeFreeze)
530
+ {-# INLINE traverseIO #-}
531
+
532
+
530
533
{-# RULES
531
534
"traverse/ST" forall f. traverse f = traverseST f
535
+ "traverse/IO" forall f. traverse f = traverseIO f
532
536
#-}
533
537
534
- -- Traversing in ST, we don't need to make a list ; we
538
+ -- Traversing in ST, we don't need to get fancy ; we
535
539
-- can just do it directly.
536
540
traverseST' :: (a -> ST s b ) -> Array a -> ST s (Array b )
537
541
traverseST' f = \ ary0 ->
538
542
let
539
543
! len = length ary0
540
- go k mary
544
+ go k ! mary
541
545
| k == len = return mary
542
546
| otherwise = do
543
547
x <- indexM ary0 k
@@ -547,8 +551,23 @@ traverseST' f = \ ary0 ->
547
551
in new_ len >>= (go 0 >=> unsafeFreeze)
548
552
{-# INLINE traverseST' #-}
549
553
554
+ traverseIO' :: (a -> IO b ) -> Array a -> IO (Array b )
555
+ traverseIO' f = \ ary0 ->
556
+ let
557
+ ! len = length ary0
558
+ go k ! mary
559
+ | k == len = return mary
560
+ | otherwise = do
561
+ x <- stToIO $ indexM ary0 k
562
+ ! y <- f x
563
+ stToIO $ write mary k y
564
+ go (k + 1 ) mary
565
+ in stToIO (new_ len) >>= (go 0 >=> stToIO . unsafeFreeze)
566
+ {-# INLINE traverseIO' #-}
567
+
550
568
{-# RULES
551
569
"traverse'/ST" forall f. traverse' f = traverseST' f
570
+ "traverse'/IO" forall f. traverse' f = traverseIO' f
552
571
#-}
553
572
554
573
filter :: (a -> Bool ) -> Array a -> Array a
0 commit comments