From 649199c02cbaa6499bd545852d937cdfff7e812f Mon Sep 17 00:00:00 2001
From: Joachim Breitner <mail@joachim-breitner.de>
Date: Sun, 18 Jun 2023 08:53:29 +0000
Subject: [PATCH] Add genArray and newGenArray

---
 Data/Array/Base.hs        | 15 +++++++++++++++
 Data/Array/IArray.hs      |  1 +
 Data/Array/MArray.hs      |  1 +
 Data/Array/MArray/Safe.hs |  1 +
 changelog.md              |  2 ++
 5 files changed, 20 insertions(+)

diff --git a/Data/Array/Base.hs b/Data/Array/Base.hs
index 2862125c..e892c4ec 100644
--- a/Data/Array/Base.hs
+++ b/Data/Array/Base.hs
@@ -195,6 +195,11 @@ listArray (l,u) es =
     let n = safeRangeSize (l,u)
     in unsafeArray (l,u) (zip [0 .. n - 1] es)
 
+{-# INLINE genArray #-}
+-- | Constructs an immutable array using a generator function.
+genArray :: (IArray a e, Ix i) => (i,i) -> (i -> e) -> a i e
+genArray (l,u) f = listArray (l,u) $ map f $ range (l,u)
+
 {-# INLINE listArrayST #-}   -- See Note [Inlining and fusion]
 listArrayST :: Ix i => (i,i) -> [e] -> ST s (STArray s i e)
 listArrayST = newListArray
@@ -906,6 +911,16 @@ newListArray (l,u) es = do
     foldr f (const (return ())) es 0
     return marr
 
+{-# INLINE newGenArray #-}
+-- | Constructs a mutable array using a generator function.
+-- It invokes the generator function in ascending order of the indices.
+newGenArray :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
+newGenArray (l,u) f = do
+    marr <- newArray_ (l,u)
+    let n = safeRangeSize (l,u)
+    sequence_ [ f i >>= unsafeWrite marr (safeIndex (l,u) n i) | i <- range (l,u)]
+    return marr
+
 {-# INLINE readArray #-}
 -- | Read an element from a mutable array
 readArray :: (MArray a e m, Ix i) => a i e -> i -> m e
diff --git a/Data/Array/IArray.hs b/Data/Array/IArray.hs
index d381d13a..5f58f7e4 100644
--- a/Data/Array/IArray.hs
+++ b/Data/Array/IArray.hs
@@ -29,6 +29,7 @@ module Data.Array.IArray (
     array,      -- :: (IArray a e, Ix i) => (i,i) -> [(i, e)] -> a i e
     listArray,  -- :: (IArray a e, Ix i) => (i,i) -> [e] -> a i e
     accumArray, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> e -> (i,i) -> [(i, e')] -> a i e
+    genArray,   -- :: (IArray a e, Ix i) => (i,i) -> (i -> e) -> a i e
 
     -- * Accessing arrays
     (!),        -- :: (IArray a e, Ix i) => a i e -> i -> e
diff --git a/Data/Array/MArray.hs b/Data/Array/MArray.hs
index 7a89f395..1f92d55b 100644
--- a/Data/Array/MArray.hs
+++ b/Data/Array/MArray.hs
@@ -27,6 +27,7 @@ module Data.Array.MArray (
     newArray,     -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)
     newArray_,    -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)
     newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
+    newGenArray,  -- :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
 
     -- * Reading and writing mutable arrays
     readArray,    -- :: (MArray a e m, Ix i) => a i e -> i -> m e
diff --git a/Data/Array/MArray/Safe.hs b/Data/Array/MArray/Safe.hs
index fcbf768c..be7a62e8 100644
--- a/Data/Array/MArray/Safe.hs
+++ b/Data/Array/MArray/Safe.hs
@@ -29,6 +29,7 @@ module Data.Array.MArray.Safe (
     newArray,     -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)
     newArray_,    -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)
     newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
+    newGenArray,  -- :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
 
     -- * Reading and writing mutable arrays
     readArray,    -- :: (MArray a e m, Ix i) => a i e -> i -> m e
diff --git a/changelog.md b/changelog.md
index d6f11e41..1e861c07 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,6 +2,8 @@
 
 ## NEXT  *TBA*
 
+  * add the `genArray` and `newGenArray` function
+
   * `listArray` and `newListArray` are now good consumers of the input list.
 
   * Unboxed Bool arrays no longer cause spurious alarms
-- 
GitLab