@@ -9,6 +9,9 @@ module Data.Array
99 ( singleton
1010 , (..), range
1111 , replicate
12+ , replicateM
13+ , some
14+ , many
1215
1316 , null
1417 , length
@@ -36,6 +39,7 @@ module Data.Array
3639 , concat
3740 , concatMap
3841 , filter
42+ , filterM
3943 , mapMaybe
4044 , catMaybes
4145
@@ -65,9 +69,9 @@ module Data.Array
6569 , zipWithA
6670 , zip
6771 , unzip
68- ) where
6972
70- import Prelude
73+ , foldM
74+ ) where
7175
7276import Control.Alt (Alt , (<|>))
7377import Control.Alternative (Alternative )
@@ -101,6 +105,28 @@ infix 8 ..
101105-- | Create an array with repeated instances of a value.
102106foreign import replicate :: forall a . Int -> a -> Array a
103107
108+ -- | Perform a monadic action `n` times collecting all of the results.
109+ replicateM :: forall m a . (Monad m ) => Int -> m a -> m (Array a )
110+ replicateM n m | n < 1 = return []
111+ | otherwise = do a <- m
112+ as <- replicateM (n - 1 ) m
113+ return (a : as)
114+
115+ -- | Attempt a computation multiple times, requiring at least one success.
116+ -- |
117+ -- | The `Lazy` constraint is used to generate the result lazily, to ensure
118+ -- | termination.
119+ some :: forall f a . (Alternative f , Lazy (f (Array a ))) => f a -> f (Array a )
120+ some v = (:) <$> v <*> defer (\_ -> many v)
121+
122+ -- | Attempt a computation multiple times, returning as many successful results
123+ -- | as possible (possibly zero).
124+ -- |
125+ -- | The `Lazy` constraint is used to generate the result lazily, to ensure
126+ -- | termination.
127+ many :: forall f a . (Alternative f , Lazy (f (Array a ))) => f a -> f (Array a )
128+ many v = some v <|> pure []
129+
104130-- ------------------------------------------------------------------------------
105131-- Array size ------------------------------------------------------------------
106132-- ------------------------------------------------------------------------------
@@ -255,6 +281,20 @@ concatMap = flip bind
255281-- | creating a new array.
256282foreign import filter :: forall a . (a -> Boolean ) -> Array a -> Array a
257283
284+ -- | Filter where the predicate returns a monadic `Boolean`.
285+ -- |
286+ -- | ```purescript
287+ -- | powerSet :: forall a. [a] -> [[a]]
288+ -- | powerSet = filterM (const [true, false])
289+ -- | ```
290+ filterM :: forall a m . (Monad m ) => (a -> m Boolean ) -> Array a -> m (Array a )
291+ filterM p = uncons' (\_ -> pure [] ) \x xs -> do
292+ b <- p x
293+ xs' <- filterM p xs
294+ return if b
295+ then x : xs'
296+ else xs'
297+
258298-- | Apply a function to each element in an array, keeping only the results
259299-- | which contain a value, creating a new array.
260300mapMaybe :: forall a b . (a -> Maybe b ) -> Array a -> Array b
@@ -430,6 +470,18 @@ unzip :: forall a b. Array (Tuple a b) -> Tuple (Array a) (Array b)
430470unzip = uncons' (\_ -> Tuple [] [] ) \(Tuple a b) ts -> case unzip ts of
431471 Tuple as bs -> Tuple (a : as) (b : bs)
432472
473+ -- ------------------------------------------------------------------------------
474+ -- Folding ---------------------------------------------------------------------
475+ -- ------------------------------------------------------------------------------
476+
477+ -- | Perform a fold using a monadic step function.
478+ foldM :: forall m a b . (Monad m ) => (a -> b -> m a ) -> a -> Array b -> m a
479+ foldM f a = uncons' (\_ -> return a) (\b bs -> f a b >>= \a' -> foldM f a' bs)
480+
481+ foreign import foldrArray :: forall a b . (a -> b -> b ) -> b -> Array a -> b
482+
483+ foreign import foldlArray :: forall a b . (b -> a -> b ) -> b -> Array a -> b
484+
433485-- ------------------------------------------------------------------------------
434486-- Non-Prelude instances -------------------------------------------------------
435487-- ------------------------------------------------------------------------------
@@ -444,5 +496,14 @@ instance alternativeArray :: Alternative Array
444496
445497instance monadPlusArray :: MonadPlus Array
446498
499+ instance foldableArray :: Foldable Array where
500+ foldr f z xs = foldrArray f z xs
501+ foldl f z xs = foldlArray f z xs
502+ foldMap f xs = foldr (\x acc -> f x <> acc) mempty xs
503+
504+ instance traversableArray :: Traversable Array where
505+ traverse f = uncons' (\_ -> pure [] ) (\x xs -> (:) <$> (f x) <*> traverse f xs)
506+ sequence = uncons' (\_ -> pure [] ) (\x xs -> (:) <$> x <*> sequence xs)
507+
447508instance invariantArray :: Invariant Array where
448509 imap = imapF
0 commit comments