Skip to content

Commit c3a11b3

Browse files
committed
Implement differenceBySorted API
1 parent 11b1989 commit c3a11b3

File tree

3 files changed

+95
-6
lines changed

3 files changed

+95
-6
lines changed

src/Streamly/Internal/Data/Stream/IsStream/Top.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ module Streamly.Internal.Data.Stream.IsStream.Top
3030
, intersectBy
3131
, intersectBySorted
3232
, differenceBy
33-
, mergeDifferenceBy
33+
, differenceBySorted
3434
, unionBy
3535
, unionBySorted
3636

@@ -633,11 +633,14 @@ differenceBy eq s1 s2 =
633633
--
634634
-- Space: O(1)
635635
--
636-
-- /Unimplemented/
637-
{-# INLINE mergeDifferenceBy #-}
638-
mergeDifferenceBy :: -- (IsStream t, Monad m) =>
636+
-- /Pre-release/
637+
{-# INLINE differenceBySorted #-}
638+
differenceBySorted :: (IsStream t, MonadIO m) =>
639639
(a -> a -> Ordering) -> t m a -> t m a -> t m a
640-
mergeDifferenceBy _eq _s1 _s2 = undefined
640+
differenceBySorted eq s1 =
641+
IsStream.fromStreamD
642+
. StreamD.differenceBySorted eq (IsStream.toStreamD s1)
643+
. IsStream.toStreamD
641644

642645
-- | This is essentially an append operation that appends all the extra
643646
-- occurrences of elements from the second stream that are not already present

src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
144144
, splitInnerBySuffix
145145
, intersectBySorted
146146
, unionBySorted
147+
, differenceBySorted
147148
)
148149
where
149150

@@ -3039,3 +3040,67 @@ unionBySorted cmp (Stream stepa ta) (Stream stepb tb) =
30393040
)
30403041

30413042
step _ (_, _, _, _, _, _, _) = return Stop
3043+
3044+
-------------------------------------------------------------------------------
3045+
-- Difference of sorted streams -----------------------------------------------
3046+
-------------------------------------------------------------------------------
3047+
{-# INLINE_NORMAL differenceBySorted #-}
3048+
differenceBySorted :: (Monad m) =>
3049+
(a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
3050+
differenceBySorted cmp (Stream stepa ta) (Stream stepb tb) =
3051+
Stream step (Just ta, Just tb, Nothing, Nothing, Nothing)
3052+
3053+
where
3054+
{-# INLINE_LATE step #-}
3055+
3056+
-- one of the values is missing, and the corresponding stream is running
3057+
step gst (Just sa, sb, Nothing, b, Nothing) = do
3058+
r <- stepa gst sa
3059+
return $ case r of
3060+
Yield a sa' -> Skip (Just sa', sb, Just a, b, Nothing)
3061+
Skip sa' -> Skip (Just sa', sb, Nothing, b, Nothing)
3062+
Stop -> Skip (Nothing, sb, Nothing, b, Nothing)
3063+
3064+
step gst (sa, Just sb, a, Nothing, Nothing) = do
3065+
r <- stepb gst sb
3066+
return $ case r of
3067+
Yield b sb' -> Skip (sa, Just sb', a, Just b, Nothing)
3068+
Skip sb' -> Skip (sa, Just sb', a, Nothing, Nothing)
3069+
Stop -> Skip (sa, Nothing, a, Nothing, Nothing)
3070+
3071+
-- Matching element
3072+
step gst (Just sa, Just sb, Nothing, _, Just _) = do
3073+
r1 <- stepa gst sa
3074+
r2 <- stepb gst sb
3075+
return $ case r1 of
3076+
Yield a sa' ->
3077+
case r2 of
3078+
Yield c sb' ->
3079+
Skip (Just sa', Just sb', Just a, Just c, Nothing)
3080+
Skip sb' ->
3081+
Skip (Just sa', Just sb', Just a, Just a, Nothing)
3082+
Stop ->
3083+
Yield a (Just sa', Just sb, Nothing, Nothing, Just a)
3084+
Skip sa' ->
3085+
case r2 of
3086+
Yield c sb' ->
3087+
Skip (Just sa', Just sb', Just c, Just c, Nothing)
3088+
Skip sb' ->
3089+
Skip (Just sa', Just sb', Nothing, Nothing, Nothing)
3090+
Stop ->
3091+
Stop
3092+
Stop ->
3093+
Stop
3094+
3095+
-- both the values are available
3096+
step _ (sa, sb, Just a, Just b, Nothing) = do
3097+
let res = cmp a b
3098+
return $ case res of
3099+
GT -> Skip (sa, sb, Just a, Nothing, Nothing)
3100+
LT -> Yield a (sa, sb, Nothing, Just b, Nothing)
3101+
EQ -> Skip (sa, sb, Nothing, Just b, Just b)
3102+
3103+
-- one of the values is missing, corresponding stream is done
3104+
step _ (sa, Nothing, Just a, Nothing, Nothing) =
3105+
return $ Yield a (sa, Nothing, Nothing, Nothing , Nothing)
3106+
step _ (_, _, _, _, _) = return Stop

test/Streamly/Test/Data/Stream/Top.hs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module Main (main)
22
where
33

4-
import Data.List (intersect, sort, union)
4+
import Data.List (intersect, sort, union, (\\))
55
import Test.QuickCheck
66
( Gen
77
, Property
@@ -64,6 +64,26 @@ unionBySorted =
6464
(S.fromList ls1)
6565
let v2 = sort $ union ls0 ls1
6666
assert (v1 == v2)
67+
68+
differenceBySorted :: Property
69+
differenceBySorted =
70+
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
71+
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
72+
monadicIO $ action (sort ls0) (sort ls1)
73+
74+
where
75+
76+
action ls0 ls1 = do
77+
v1 <-
78+
run
79+
$ S.toList
80+
$ Top.differenceBySorted
81+
compare
82+
(S.fromList ls0)
83+
(S.fromList ls1)
84+
let v2 = ls0 \\ ls1
85+
assert (v1 == sort v2)
86+
6787
-------------------------------------------------------------------------------
6888
moduleName :: String
6989
moduleName = "Data.Stream.Top"
@@ -74,3 +94,4 @@ main = hspec $ do
7494
-- intersect
7595
prop "intersectBySorted" Main.intersectBySorted
7696
prop "unionBySorted" Main.unionBySorted
97+
prop "differenceBySorted" Main.differenceBySorted

0 commit comments

Comments
 (0)