Add mapMaybe to sets and Seq#1159
Conversation
|
Thank you for the PR! @treeowl, would you agree? |
|
I also don't think we really need traverseMaybe :: Applicative f => (a -> f (Maybe b)) -> Whatever a -> f (Whatever b) |
|
And what about |
That's a good question, but there's a problem since we are doing a tail-recursive construction with an accumulator. To keep the same style, we need I'm fine with considering this later, doesn't have to be in this PR. |
|
Thanks for the comments, will get to them at some point.
|
|
For Also, I still want |
|
To clarify, |
|
Sorry, I seem to have half-remembered some bits. I need to look through again. |
|
I think I've resolved all the comments above, except I didn't add |
I did do a benchmark, and a dedicated diff --git a/containers-tests/benchmarks/Set.hs b/containers-tests/benchmarks/Set.hs
index 9e367391..6708cba6 100644
--- a/containers-tests/benchmarks/Set.hs
+++ b/containers-tests/benchmarks/Set.hs
@@ -7,6 +7,7 @@ import Control.Exception (evaluate)
import Test.Tasty.Bench (bench, bgroup, defaultMain, whnf)
import Data.List (foldl')
import qualified Data.Set as S
+import qualified Data.Set.Internal as S
import Utils.Fold (foldBenchmarks)
import Utils.Random (shuffle)
@@ -16,6 +17,7 @@ main = do
s_even = S.fromList elems_even :: S.Set Int
s_odd = S.fromList elems_odd :: S.Set Int
strings_s = S.fromList strings
+ s_maybe = S.insert Nothing $ S.map Just s
evaluate $ rnf [s, s_even, s_odd]
evaluate $ rnf
[elems_distinct_asc, elems_distinct_desc, elems_asc, elems_desc]
@@ -68,6 +70,8 @@ main = do
, bench "eq" $ whnf (\s' -> s' == s') s -- worst case, compares everything
, bench "compare" $ whnf (\s' -> compare s' s') s -- worst case, compares everything
, bgroup "folds" $ foldBenchmarks S.foldr S.foldl S.foldr' S.foldl' foldMap s
+ , bench "catMaybes1" $ whnf S.catMaybes1 s_maybe
+ , bench "catMaybes2" $ whnf S.catMaybes2 s_maybe
]
where
bound = 2^12
diff --git a/containers/src/Data/Set/Internal.hs b/containers/src/Data/Set/Internal.hs
index 0af7eb15..a330491f 100644
--- a/containers/src/Data/Set/Internal.hs
+++ b/containers/src/Data/Set/Internal.hs
@@ -163,6 +163,8 @@ module Data.Set.Internal (
, dropWhileAntitone
, spanAntitone
, mapMaybe
+ , catMaybes1
+ , catMaybes2
, partition
, split
, splitMember
@@ -231,6 +233,7 @@ module Data.Set.Internal (
import Utils.Containers.Internal.Prelude hiding
(filter,foldl,foldl',foldr,null,map,take,drop,splitAt)
+import qualified Data.Maybe as Maybe
import Prelude ()
import Control.Applicative (Const(..))
import qualified Data.List as List
@@ -1011,6 +1014,13 @@ mapMaybe f t = finishB (foldl' go emptyB t)
Just x' -> insertB x' b
{-# INLINABLE mapMaybe #-}
+catMaybes1, catMaybes2 :: Ord a => Set (Maybe a) -> Set a
+{-# INLINABLE catMaybes1 #-}
+{-# INLINABLE catMaybes2 #-}
+
+catMaybes1 = mapMaybe id
+catMaybes2 = mapMonotonic Maybe.fromJust . dropWhileAntitone Maybe.isNothing
+
{----------------------------------------------------------------------
Map
----------------------------------------------------------------------}I get I still don't feel strongly about including it. |
meooow25
left a comment
There was a problem hiding this comment.
Thank you, just a couple of minor comments.
I did do a benchmark, and a dedicated catMaybes can indeed be more efficient.
That's a good point about Set, since Nothing will always be the minimum value.
I still don't feel strongly about including it.
I agree, if someone really wants this we can consider adding it later.
|
Thanks, updated. |
catMaybes and mapMaybe to sets, maps and SeqmapMaybe to sets, maps and Seq
mapMaybe to sets, maps and SeqmapMaybe to sets and Seq
As discussed in #346. We now have
mapMaybein all ofSeq,Set,IntSet, strict and lazyMap, and strict and lazyIntMap.AndThe issue doesn't mention all of them, but I figured it would be good to have a consistent API.catMaybesin all of those exceptIntSet(where it doesn't make sense).