From af7f4807b2f067125da7c19bb162803093c38bf6 Mon Sep 17 00:00:00 2001 From: Cyril Sobierajewicz Date: Sun, 13 Dec 2020 14:59:20 +0100 Subject: [PATCH 1/3] Remove fold1 from Foldable1 --- src/Data/Semigroup/Foldable.purs | 44 ++++++-------------------------- test/Main.purs | 5 ++-- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/src/Data/Semigroup/Foldable.purs b/src/Data/Semigroup/Foldable.purs index e16006d..6959c79 100644 --- a/src/Data/Semigroup/Foldable.purs +++ b/src/Data/Semigroup/Foldable.purs @@ -7,10 +7,6 @@ module Data.Semigroup.Foldable , traverse1_ , for1_ , sequence1_ - , foldMap1Default - , fold1Default - , fold1DefaultR - , fold1DefaultL , foldr1Default , foldl1Default , intercalate @@ -32,44 +28,18 @@ import Data.Ord.Min (Min(..)) -- | `Foldable1` represents data structures with a minimum of one element that can be _folded_. -- | --- | - `fold1` folds a structure using a `Semigroup` instance --- | - `foldMap1` folds a structure by accumulating values in a `Semigroup` -- | - `foldr1` folds a structure from the right -- | - `foldl1` folds a structure from the left +-- | - `foldMap1` folds a structure by accumulating values in a `Semigroup` -- | -- | Default implementations are provided by the following functions: -- | --- | - `fold1Default` --- | - `fold1DefaultR` --- | - `fold1DefaultL` --- | - `foldMap1Default` -- | - `foldr1Default` -- | - `foldl1Default` --- | --- | Note: some combinations of the default implementations are unsafe to --- | use together - causing a non-terminating mutually recursive cycle. --- | These combinations are documented per function. class Foldable t <= Foldable1 t where - foldMap1 :: forall a m. Semigroup m => (a -> m) -> t a -> m - fold1 :: forall m. Semigroup m => t m -> m foldr1 :: forall a. (a -> a -> a) -> t a -> a foldl1 :: forall a. (a -> a -> a) -> t a -> a - --- | A default implementation of `fold1` using `foldMap1`. -fold1Default :: forall t m. Foldable1 t => Semigroup m => t m -> m -fold1Default = foldMap1 identity - --- | A default implementation of `fold1` using `foldr1`. -fold1DefaultR :: forall t m. Foldable1 t => Semigroup m => t m -> m -fold1DefaultR = foldr1 append - --- | A default implementation of `fold1` using `foldl1`. -fold1DefaultL :: forall t m. Foldable1 t => Semigroup m => t m -> m -fold1DefaultL = foldl1 append - --- | A default implementation of `foldMap1` using `fold1`. -foldMap1Default :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m -foldMap1Default f = (map f) >>> fold1 + foldMap1 :: forall a m. Semigroup m => (a -> m) -> t a -> m -- | A default implementation of `foldr1` using `foldMap1`. foldr1Default :: forall t a. Foldable1 t => (a -> a -> a) -> t a -> a @@ -80,16 +50,18 @@ foldl1Default :: forall t a. Foldable1 t => (a -> a -> a) -> t a -> a foldl1Default = flip (runFoldRight1 <<< alaF Dual foldMap1 mkFoldRight1) <<< flip instance foldableDual :: Foldable1 Dual where - foldMap1 f (Dual x) = f x - fold1 = fold1Default foldr1 _ (Dual x) = x foldl1 _ (Dual x) = x + foldMap1 f (Dual x) = f x instance foldableMultiplicative :: Foldable1 Multiplicative where - foldMap1 f (Multiplicative x) = f x - fold1 = fold1Default foldr1 _ (Multiplicative x) = x foldl1 _ (Multiplicative x) = x + foldMap1 f (Multiplicative x) = f x + +-- | Fold a data structure, accumulating values in some `Semigroup`. +fold1 :: forall t m. Foldable1 t => Semigroup m => t m -> m +fold1 = foldMap1 identity newtype Act :: forall k. (k -> Type) -> k -> Type newtype Act f a = Act (f a) diff --git a/test/Main.purs b/test/Main.purs index 9f86a01..9579f3c 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -13,7 +13,7 @@ import Data.Int (toNumber, pow) import Data.Maybe (Maybe(..)) import Data.Monoid.Additive (Additive(..)) import Data.Newtype (unwrap) -import Data.Semigroup.Foldable (class Foldable1, foldr1, foldl1, fold1Default, foldr1Default, foldl1Default) +import Data.Semigroup.Foldable (class Foldable1, foldr1, foldl1, foldr1Default, foldl1Default) import Data.Semigroup.Foldable as Foldable1 import Data.Traversable (class Traversable, sequenceDefault, traverse, sequence, traverseDefault) import Data.TraversableWithIndex (class TraversableWithIndex, traverseWithIndex) @@ -36,10 +36,9 @@ instance foldableNEArray :: Foldable NEArray where foldr f = foldrDefault f instance foldable1NEArray :: Foldable1 NEArray where - foldMap1 = foldMap1NEArray append - fold1 = fold1Default foldr1 f = foldr1Default f foldl1 f = foldl1Default f + foldMap1 = foldMap1NEArray append maybeMkNEArray :: forall a. Array a -> Maybe (NEArray a) maybeMkNEArray = mkNEArray Nothing Just From daa432ba422997b3719152be0bfedf14d7750da5 Mon Sep 17 00:00:00 2001 From: Cyril Sobierajewicz Date: Sun, 27 Dec 2020 18:36:56 +0100 Subject: [PATCH 2/3] Add back foldMap1Default --- src/Data/Semigroup/Foldable.purs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Data/Semigroup/Foldable.purs b/src/Data/Semigroup/Foldable.purs index 6959c79..06bdab4 100644 --- a/src/Data/Semigroup/Foldable.purs +++ b/src/Data/Semigroup/Foldable.purs @@ -9,6 +9,7 @@ module Data.Semigroup.Foldable , sequence1_ , foldr1Default , foldl1Default + , foldMap1Default , intercalate , intercalateMap , maximum @@ -36,6 +37,11 @@ import Data.Ord.Min (Min(..)) -- | -- | - `foldr1Default` -- | - `foldl1Default` +-- | - `foldMap1Default` +-- | +-- | Note: some combinations of the default implementations are unsafe to +-- | use together - causing a non-terminating mutually recursive cycle. +-- | These combinations are documented per function. class Foldable t <= Foldable1 t where foldr1 :: forall a. (a -> a -> a) -> t a -> a foldl1 :: forall a. (a -> a -> a) -> t a -> a @@ -46,9 +52,19 @@ foldr1Default :: forall t a. Foldable1 t => (a -> a -> a) -> t a -> a foldr1Default = flip (runFoldRight1 <<< foldMap1 mkFoldRight1) -- | A default implementation of `foldl1` using `foldMap1`. +-- | +-- | Note: when defining a `Foldable1` instance, this function is unsafe to use +-- | in combination with `foldMap1Default`. foldl1Default :: forall t a. Foldable1 t => (a -> a -> a) -> t a -> a foldl1Default = flip (runFoldRight1 <<< alaF Dual foldMap1 mkFoldRight1) <<< flip +-- | A default implementation of `foldMap1` using `foldl1`. +-- | +-- | Note: when defining a `Foldable1` instance, this function is unsafe to use +-- | in combination with `foldl1Default`. +foldMap1Default :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m +foldMap1Default f = map f >>> foldl1 (<>) + instance foldableDual :: Foldable1 Dual where foldr1 _ (Dual x) = x foldl1 _ (Dual x) = x From 22a758778bc5691c676aac8de826d5a6345c6b3b Mon Sep 17 00:00:00 2001 From: Cyril Sobierajewicz Date: Sun, 27 Dec 2020 18:58:55 +0100 Subject: [PATCH 3/3] Deprecate and split foldMap1Default into foldMap1DefaultL and foldMap1DefaultR --- src/Data/Semigroup/Foldable.purs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Data/Semigroup/Foldable.purs b/src/Data/Semigroup/Foldable.purs index 06bdab4..7728612 100644 --- a/src/Data/Semigroup/Foldable.purs +++ b/src/Data/Semigroup/Foldable.purs @@ -9,6 +9,8 @@ module Data.Semigroup.Foldable , sequence1_ , foldr1Default , foldl1Default + , foldMap1DefaultR + , foldMap1DefaultL , foldMap1Default , intercalate , intercalateMap @@ -26,6 +28,7 @@ import Data.Monoid.Multiplicative (Multiplicative(..)) import Data.Newtype (ala, alaF) import Data.Ord.Max (Max(..)) import Data.Ord.Min (Min(..)) +import Prim.TypeError (class Warn, Text) -- | `Foldable1` represents data structures with a minimum of one element that can be _folded_. -- | @@ -37,7 +40,8 @@ import Data.Ord.Min (Min(..)) -- | -- | - `foldr1Default` -- | - `foldl1Default` --- | - `foldMap1Default` +-- | - `foldMap1DefaultR` +-- | - `foldMap1DefaultL` -- | -- | Note: some combinations of the default implementations are unsafe to -- | use together - causing a non-terminating mutually recursive cycle. @@ -48,22 +52,36 @@ class Foldable t <= Foldable1 t where foldMap1 :: forall a m. Semigroup m => (a -> m) -> t a -> m -- | A default implementation of `foldr1` using `foldMap1`. +-- | +-- | Note: when defining a `Foldable1` instance, this function is unsafe to use +-- | in combination with `foldMap1DefaultR`. foldr1Default :: forall t a. Foldable1 t => (a -> a -> a) -> t a -> a foldr1Default = flip (runFoldRight1 <<< foldMap1 mkFoldRight1) -- | A default implementation of `foldl1` using `foldMap1`. -- | -- | Note: when defining a `Foldable1` instance, this function is unsafe to use --- | in combination with `foldMap1Default`. +-- | in combination with `foldMap1DefaultL`. foldl1Default :: forall t a. Foldable1 t => (a -> a -> a) -> t a -> a foldl1Default = flip (runFoldRight1 <<< alaF Dual foldMap1 mkFoldRight1) <<< flip +-- | A default implementation of `foldMap1` using `foldr1`. +-- | +-- | Note: when defining a `Foldable1` instance, this function is unsafe to use +-- | in combination with `foldr1Default`. +foldMap1DefaultR :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m +foldMap1DefaultR f = map f >>> foldr1 (<>) + -- | A default implementation of `foldMap1` using `foldl1`. -- | -- | Note: when defining a `Foldable1` instance, this function is unsafe to use -- | in combination with `foldl1Default`. -foldMap1Default :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m -foldMap1Default f = map f >>> foldl1 (<>) +foldMap1DefaultL :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m +foldMap1DefaultL f = map f >>> foldl1 (<>) + +-- | Deprecated previous name of `foldMap1DefaultL`. +foldMap1Default :: forall t m a. Warn (Text "'foldMap1Default' is deprecated, use 'foldMap1DefaultL' instead") => Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m +foldMap1Default = foldMap1DefaultL instance foldableDual :: Foldable1 Dual where foldr1 _ (Dual x) = x