From ff7f68adb5693764fb8fb0ded35bcaf09de78bd2 Mon Sep 17 00:00:00 2001 From: chessai Date: Sat, 14 Jul 2018 20:05:27 -0400 Subject: [PATCH 1/9] foldMap, foldMap' --- Data/Primitive/PrimArray.hs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Data/Primitive/PrimArray.hs b/Data/Primitive/PrimArray.hs index f333c1ec..7511e75e 100644 --- a/Data/Primitive/PrimArray.hs +++ b/Data/Primitive/PrimArray.hs @@ -66,6 +66,8 @@ module Data.Primitive.PrimArray , foldlPrimArray , foldlPrimArray' , foldlPrimArrayM' + , foldMapPrimArray + , foldMapPrimArray' -- * Effectful Folding , traversePrimArray_ , itraversePrimArray_ @@ -467,6 +469,16 @@ sizeofPrimArray :: forall a. Prim a => PrimArray a -> Int {-# INLINE sizeofPrimArray #-} sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# (undefined :: a))) +-- | Lazily map each element of the primitive array to a monoid, and combine the results. +foldMapPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +{-# INLINE foldMapPrimArray #-} +foldMapPrimArray f = foldrPrimArray (\a acc -> acc `mappend` f a) mempty + +-- | Strictly map each element of the primitive array to a monoid, and combine the results. +foldMapPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +{-# INLINE foldMapPrimArray' #-} +foldMapPrimArray' f = foldlPrimArray' (\ !acc x -> acc `mappend` f x) mempty + -- | Lazy right-associated fold over the elements of a 'PrimArray'. {-# INLINE foldrPrimArray #-} foldrPrimArray :: forall a b. Prim a => (a -> b -> b) -> b -> PrimArray a -> b From 694853605eed22944405b429a6c72943ee62ef7b Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 16 Jul 2018 15:24:13 -0400 Subject: [PATCH 2/9] update changelog --- changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index b5f5ed22..ac0ee08e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,8 @@ ## Changes in version 0.6.4.1 - * Add instances for the following newtypes from `base`: + * Add `foldMapPrimArray` and `foldMapPrimArray'` + + * Add `Prim` instances for the following newtypes from `base`: `Const`, `Identity`, `Down`, `Dual`, `Sum`, `Product`, `First`, `Last`, `Min`, `Max` From af41b39f455a32a2c9d67eff3879731a955aecd0 Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 17 Sep 2018 15:54:04 -0400 Subject: [PATCH 3/9] fix ordering of mappend in foldMapPrimArray --- Data/Primitive/PrimArray.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/Primitive/PrimArray.hs b/Data/Primitive/PrimArray.hs index 7511e75e..1573ecfa 100644 --- a/Data/Primitive/PrimArray.hs +++ b/Data/Primitive/PrimArray.hs @@ -472,7 +472,7 @@ sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# -- | Lazily map each element of the primitive array to a monoid, and combine the results. foldMapPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldMapPrimArray #-} -foldMapPrimArray f = foldrPrimArray (\a acc -> acc `mappend` f a) mempty +foldMapPrimArray f = foldrPrimArray (\a acc -> f a `mappend` acc) mempty -- | Strictly map each element of the primitive array to a monoid, and combine the results. foldMapPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m From 0bb9dd6304696b2ce282f84eb6daecadf1c55958 Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 17 Sep 2018 16:49:57 -0400 Subject: [PATCH 4/9] have 4 foldMaps; two right, two left, two lazy, two strict, red fish, blue fish --- Data/Primitive/PrimArray.hs | 40 +++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/Data/Primitive/PrimArray.hs b/Data/Primitive/PrimArray.hs index 1573ecfa..24932101 100644 --- a/Data/Primitive/PrimArray.hs +++ b/Data/Primitive/PrimArray.hs @@ -66,8 +66,10 @@ module Data.Primitive.PrimArray , foldlPrimArray , foldlPrimArray' , foldlPrimArrayM' - , foldMapPrimArray - , foldMapPrimArray' + , foldrMapPrimArray + , foldlMapPrimArray + , foldrMapPrimArray' + , foldlMapPrimArray' -- * Effectful Folding , traversePrimArray_ , itraversePrimArray_ @@ -469,15 +471,31 @@ sizeofPrimArray :: forall a. Prim a => PrimArray a -> Int {-# INLINE sizeofPrimArray #-} sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# (undefined :: a))) --- | Lazily map each element of the primitive array to a monoid, and combine the results. -foldMapPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m -{-# INLINE foldMapPrimArray #-} -foldMapPrimArray f = foldrPrimArray (\a acc -> f a `mappend` acc) mempty - --- | Strictly map each element of the primitive array to a monoid, and combine the results. -foldMapPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m -{-# INLINE foldMapPrimArray' #-} -foldMapPrimArray' f = foldlPrimArray' (\ !acc x -> acc `mappend` f x) mempty +-- | Map each element of the primitive array to a monoid, and combine the results. +-- The combination is right-associated, and the accumulation is lazy. +foldrMapPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +{-# INLINE foldrMapPrimArray #-} +foldrMapPrimArray f = foldrPrimArray (\a acc -> f a `mappend` acc) mempty + +-- | Map each element of the primitive array to a monoid, and combine the results. +-- The combination is left-associated, and the accumulation is lazy. +foldlMapPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +{-# INLINE foldlMapPrimArray #-} +foldlMapPrimArray f = foldlPrimArray (\acc a -> acc `mappend` f a) mempty + +-- | Map each element of the primitive array to a monoid, and combine the results. +-- The combination is right-associated, and the accumulation is strict, though +-- this function is not necessarily strict in its result. +foldrMapPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +{-# INLINE foldrMapPrimArray' #-} +foldrMapPrimArray' f = foldrPrimArray (\a !acc -> f a `mappend` acc) mempty + +-- | Map each element of the primitive array to a monoid, and combine the results. +-- The combination is left-associated, and the accumulation is strict, though +-- this function is not necessarily strict in its result. +foldlMapPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +{-# INLINE foldlMapPrimArray' #-} +foldlMapPrimArray' f = foldlPrimArray (\ !acc a -> acc `mappend` f a) mempty -- | Lazy right-associated fold over the elements of a 'PrimArray'. {-# INLINE foldrPrimArray #-} From 8aaa9d1fbccd29e3d68631dc8c06bb908a4d95da Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 17 Sep 2018 17:37:56 -0400 Subject: [PATCH 5/9] bump quickcheck-classes for travis happiness --- test/primitive-tests.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/primitive-tests.cabal b/test/primitive-tests.cabal index 1e037c8f..07524a15 100644 --- a/test/primitive-tests.cabal +++ b/test/primitive-tests.cabal @@ -38,7 +38,7 @@ test-suite test , tasty-quickcheck , tagged , transformers >= 0.3 - , quickcheck-classes >= 0.4.11.1 + , quickcheck-classes >= 0.4.14.2 ghc-options: -O2 source-repository head From 96eb0ccc808cc807ac2609f8875ca86b108fc195 Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 17 Sep 2018 21:02:10 -0400 Subject: [PATCH 6/9] change fold{dir}MapPrimArray to foldMap{dir}PrimArray, and mention all in changelog --- Data/Primitive/PrimArray.hs | 30 ++++++++++++++++-------------- changelog.md | 3 ++- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Data/Primitive/PrimArray.hs b/Data/Primitive/PrimArray.hs index 24932101..007b87a8 100644 --- a/Data/Primitive/PrimArray.hs +++ b/Data/Primitive/PrimArray.hs @@ -66,10 +66,10 @@ module Data.Primitive.PrimArray , foldlPrimArray , foldlPrimArray' , foldlPrimArrayM' - , foldrMapPrimArray - , foldlMapPrimArray - , foldrMapPrimArray' - , foldlMapPrimArray' + , foldMapRPrimArray + , foldMapLPrimArray + , foldMapRPrimArray' + , foldMapLPrimArray' -- * Effectful Folding , traversePrimArray_ , itraversePrimArray_ @@ -473,29 +473,31 @@ sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is right-associated, and the accumulation is lazy. -foldrMapPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +foldMapRPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldrMapPrimArray #-} -foldrMapPrimArray f = foldrPrimArray (\a acc -> f a `mappend` acc) mempty +foldMapRPrimArray f = foldrPrimArray (\a acc -> f a `mappend` acc) mempty -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is left-associated, and the accumulation is lazy. -foldlMapPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +foldMapLPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldlMapPrimArray #-} -foldlMapPrimArray f = foldlPrimArray (\acc a -> acc `mappend` f a) mempty +foldMapLPrimArray f = foldlPrimArray (\acc a -> acc `mappend` f a) mempty -- | Map each element of the primitive array to a monoid, and combine the results. --- The combination is right-associated, and the accumulation is strict, though --- this function is not necessarily strict in its result. -foldrMapPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +-- The combination is right-associated, and the accumulation is strict. At each +-- step, we force the accumulator value to WHNF, but we /don't/ force the value +-- of 'f a', meaning that if 'mappend' is lazy in its first argument, 'f a' will +-- not be evaluated. +foldMapRPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldrMapPrimArray' #-} -foldrMapPrimArray' f = foldrPrimArray (\a !acc -> f a `mappend` acc) mempty +foldMapRPrimArray' f = foldrPrimArray (\a !acc -> f a `mappend` acc) mempty -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is left-associated, and the accumulation is strict, though -- this function is not necessarily strict in its result. -foldlMapPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m +foldMapLPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldlMapPrimArray' #-} -foldlMapPrimArray' f = foldlPrimArray (\ !acc a -> acc `mappend` f a) mempty +foldMapLPrimArray' f = foldlPrimArray (\ !acc a -> acc `mappend` f a) mempty -- | Lazy right-associated fold over the elements of a 'PrimArray'. {-# INLINE foldrPrimArray #-} diff --git a/changelog.md b/changelog.md index 0c41d51e..426fc728 100644 --- a/changelog.md +++ b/changelog.md @@ -29,7 +29,8 @@ ## Changes in version 0.6.4.1 - * Add `foldMapPrimArray` and `foldMapPrimArray'` + * Add `foldMapRPrimArray` , `foldMapLPrimArray`, `foldMapRPrimArray'`, and + `foldMapLPrimArray'` * Add `Prim` instances for the following newtypes from `base`: `Const`, `Identity`, `Down`, `Dual`, `Sum`, `Product`, From 534a20c4975193b6b6a938b6de23152fd939e6d3 Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 17 Sep 2018 21:42:16 -0400 Subject: [PATCH 7/9] provide an example to demonstrate association and accumulation, correct some documentation on strict folds --- Data/Primitive/PrimArray.hs | 49 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/Data/Primitive/PrimArray.hs b/Data/Primitive/PrimArray.hs index 007b87a8..ff85dc34 100644 --- a/Data/Primitive/PrimArray.hs +++ b/Data/Primitive/PrimArray.hs @@ -473,30 +473,61 @@ sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is right-associated, and the accumulation is lazy. +-- An example: +-- +-- @mySum = 'Data.Monoid.getSum' '$' 'foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2,3,4])@ +-- +-- Because the accumulation of 'foldMapRPrimArray' is /right-associative/, accumulation starts from the right. The first accumulation looks like this: +-- +-- @mySum = 'Data.Monoid.getSum' '$' ('foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2,3])) '<>' ('Data.Monoid.Sum' 4 '<>' 'mempty')@ +-- +-- At each step, we don't force the value of the /accumulator/, in this case 'mempty' (and in the next case the result of @'Data.Monoid.Sum' 4 '<>' 'mempty'@). +-- This is what it means for accumulation to be lazy. Continuing: +-- +-- @mySum = 'Data.Monoid.getSum' '$' ('foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2])) '<>' ('Data.Monoid.Sum' 3 '<>' ('Data.Monoid.Sum' 4 '<>' 'mempty'))@ +-- +-- As you can see, we are accumulating thunks because we never force the value of the accumulator, so @'Data.Monoid.Sum' 4 '<>' 'mempty'@ is not calculated until the end. +-- Fully 'built-up', the thunks look like this: +-- +-- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 3 '<>' ('Data.Monoid.Sum' 4 '<>' 'mempty'))))@ +-- +-- And now that we've built up the thunks, we need to actually accumulate them to get our answer: +-- +-- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 3 '<>' 'Data.Monoid.Sum' 4)))@ +-- +-- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 7)))@ +-- +-- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 9)@ +-- +-- @mySum = 'Data.Monoid.getSum' '$' 'Data.Monoid.Sum' 10@ +-- +-- @mySum = 10@ foldMapRPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m -{-# INLINE foldrMapPrimArray #-} +{-# INLINE foldMapRPrimArray #-} foldMapRPrimArray f = foldrPrimArray (\a acc -> f a `mappend` acc) mempty -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is left-associated, and the accumulation is lazy. foldMapLPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m -{-# INLINE foldlMapPrimArray #-} +{-# INLINE foldMapLPrimArray #-} foldMapLPrimArray f = foldlPrimArray (\acc a -> acc `mappend` f a) mempty -- | Map each element of the primitive array to a monoid, and combine the results. --- The combination is right-associated, and the accumulation is strict. At each --- step, we force the accumulator value to WHNF, but we /don't/ force the value --- of 'f a', meaning that if 'mappend' is lazy in its first argument, 'f a' will +-- The combination is right-associated, and the accumulation is strict. This means +-- that at each step, we force the accumulator value to WHNF, but we /don't/ force the value +-- of the result of the function argument at each point, meaning that if 'mappend' is lazy in its first argument, that result will -- not be evaluated. foldMapRPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m -{-# INLINE foldrMapPrimArray' #-} +{-# INLINE foldMapRPrimArray' #-} foldMapRPrimArray' f = foldrPrimArray (\a !acc -> f a `mappend` acc) mempty -- | Map each element of the primitive array to a monoid, and combine the results. --- The combination is left-associated, and the accumulation is strict, though --- this function is not necessarily strict in its result. +-- The combination is left-associated, and the accumulation is strict. This means +-- that at each step, we force the accumulator value to WHNF, but we /don't/ force the value +-- +-- of the result of the function argument at each point, meaning that if 'mappend' is lazy in its second argument, that result will not be evaluated. foldMapLPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m -{-# INLINE foldlMapPrimArray' #-} +{-# INLINE foldMapLPrimArray' #-} foldMapLPrimArray' f = foldlPrimArray (\ !acc a -> acc `mappend` f a) mempty -- | Lazy right-associated fold over the elements of a 'PrimArray'. From 6f0c84e51e189d65855f52339b871377abb5075f Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 17 Sep 2018 22:43:07 -0400 Subject: [PATCH 8/9] simplify examples for foldMapRPrimArray foldMapLPrimArray --- Data/Primitive/PrimArray.hs | 47 +++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/Data/Primitive/PrimArray.hs b/Data/Primitive/PrimArray.hs index ff85dc34..72762248 100644 --- a/Data/Primitive/PrimArray.hs +++ b/Data/Primitive/PrimArray.hs @@ -473,41 +473,48 @@ sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is right-associated, and the accumulation is lazy. --- An example: -- --- @mySum = 'Data.Monoid.getSum' '$' 'foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2,3,4])@ +-- ==== __Examples__ -- --- Because the accumulation of 'foldMapRPrimArray' is /right-associative/, accumulation starts from the right. The first accumulation looks like this: +-- @mySum = 'Data.Monoid.getSum' '$' 'foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2,3])@ -- --- @mySum = 'Data.Monoid.getSum' '$' ('foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2,3])) '<>' ('Data.Monoid.Sum' 4 '<>' 'mempty')@ +-- @mySum = 'Data.Monoid.getSum' '$' ('foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2])) '<>' ('Data.Monoid.Sum' 3 '<>' 'mempty')@ -- --- At each step, we don't force the value of the /accumulator/, in this case 'mempty' (and in the next case the result of @'Data.Monoid.Sum' 4 '<>' 'mempty'@). --- This is what it means for accumulation to be lazy. Continuing: +-- @mySum = 'Data.Monoid.getSum' '$' ('foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1])) '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 3 '<>' 'mempty'))@ -- --- @mySum = 'Data.Monoid.getSum' '$' ('foldMapRPrimArray' 'Data.Monoid.Sum' ('fromList' [1,2])) '<>' ('Data.Monoid.Sum' 3 '<>' ('Data.Monoid.Sum' 4 '<>' 'mempty'))@ +-- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 3 '<>' 'mempty')))@ -- --- As you can see, we are accumulating thunks because we never force the value of the accumulator, so @'Data.Monoid.Sum' 4 '<>' 'mempty'@ is not calculated until the end. --- Fully 'built-up', the thunks look like this: +-- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' 'Data.Monoid.Sum' 3))@ -- --- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 3 '<>' ('Data.Monoid.Sum' 4 '<>' 'mempty'))))@ --- --- And now that we've built up the thunks, we need to actually accumulate them to get our answer: --- --- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 3 '<>' 'Data.Monoid.Sum' 4)))@ --- --- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 2 '<>' ('Data.Monoid.Sum' 7)))@ --- --- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' ('Data.Monoid.Sum' 9)@ +-- @mySum = 'Data.Monoid.getSum' '$' ('Data.Monoid.Sum' 1 '<>' 'Data.Monoid.Sum' 5)@ -- --- @mySum = 'Data.Monoid.getSum' '$' 'Data.Monoid.Sum' 10@ +-- @mySum = 'Data.Monoid.getSum' '$' 'Data.Monoid.Sum' 6@ -- --- @mySum = 10@ +-- @mySum = 6@ foldMapRPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldMapRPrimArray #-} foldMapRPrimArray f = foldrPrimArray (\a acc -> f a `mappend` acc) mempty -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is left-associated, and the accumulation is lazy. +-- +-- ==== __Examples__ +-- +-- @myProd = 'Data.Monoid.getProduct' '$' 'foldMapLPrimArray' 'Data.Monoid.Product' ('fromList' [1,2,3])@ +-- +-- @myProd = 'Data.Monoid.getProduct' '$' ('mempty' '<>' 'Data.Monoid.Product' 1) '<>' ('foldMapLPrimArray' 'Data.Monoid.Product' ('fromList' [2,3])@ +-- +-- @myProd = 'Data.Monoid.getProduct' '$' (('mempty' '<>' 'Data.Monoid.Product' 1) '<>' 'Data.Monoid.Product' 2) '<>' ('foldMapLPrimArray' 'Data.Monoid.Product' ('fromList' [3]))@ +-- +-- @myProd = 'Data.Monoid.getProduct' '$' ((('mempty' '<>' 'Data.Monoid.Product' 1) '<>' 'Data.Monoid.Product' 2) '<>' 'Data.Monoid.Product' 3)@ +-- +-- @myProd = 'Data.Monoid.getProduct' '$' (('Data.Monoid.Product' 1 '<>' 'Data.Monoid.Product' 2) '<>' 'Data.Monoid.Product' 3)@ +-- +-- @myProd = 'Data.Monoid.getProduct' '$' ('Data.Monoid.Product' 2 '<>' 'Data.Monoid.Product' 3)@ +-- +-- @myProd = 'Data.Monoid.getProduct' '$' 'Data.Monoid.Product' 6@ +-- +-- @myProd = 6@ foldMapLPrimArray :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldMapLPrimArray #-} foldMapLPrimArray f = foldlPrimArray (\acc a -> acc `mappend` f a) mempty From d4eb3d0c5f57ada634b5c32b28d38d9485c7f195 Mon Sep 17 00:00:00 2001 From: chessai Date: Mon, 17 Sep 2018 22:52:33 -0400 Subject: [PATCH 9/9] make strict foldMaps on PrimArray force function value at each step --- Data/Primitive/PrimArray.hs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Data/Primitive/PrimArray.hs b/Data/Primitive/PrimArray.hs index 72762248..4e730a0d 100644 --- a/Data/Primitive/PrimArray.hs +++ b/Data/Primitive/PrimArray.hs @@ -521,21 +521,21 @@ foldMapLPrimArray f = foldlPrimArray (\acc a -> acc `mappend` f a) mempty -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is right-associated, and the accumulation is strict. This means --- that at each step, we force the accumulator value to WHNF, but we /don't/ force the value --- of the result of the function argument at each point, meaning that if 'mappend' is lazy in its first argument, that result will --- not be evaluated. +-- that at each step, we force the accumulator value to WHNF. We also force the value +-- of the result of the function argument at each point, meaning that both arguments +-- of 'mappend' will be evaluated. foldMapRPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldMapRPrimArray' #-} -foldMapRPrimArray' f = foldrPrimArray (\a !acc -> f a `mappend` acc) mempty +foldMapRPrimArray' f = foldrPrimArray (\ a !acc -> let !fa = f $! a in fa `mappend` acc) mempty -- | Map each element of the primitive array to a monoid, and combine the results. -- The combination is left-associated, and the accumulation is strict. This means --- that at each step, we force the accumulator value to WHNF, but we /don't/ force the value --- --- of the result of the function argument at each point, meaning that if 'mappend' is lazy in its second argument, that result will not be evaluated. +-- that at each step, we force the accumulator value to WHNF. We also force the value +-- of the result of the function argument at each point, meaning that both arguments +-- of 'mappend' will be evaulated. foldMapLPrimArray' :: forall a m. (Prim a, Monoid m) => (a -> m) -> PrimArray a -> m {-# INLINE foldMapLPrimArray' #-} -foldMapLPrimArray' f = foldlPrimArray (\ !acc a -> acc `mappend` f a) mempty +foldMapLPrimArray' f = foldlPrimArray (\ !acc a -> let !fa = f $! a in acc `mappend` fa) mempty -- | Lazy right-associated fold over the elements of a 'PrimArray'. {-# INLINE foldrPrimArray #-}