@@ -225,6 +225,13 @@ module Streaming.Prelude (
225225 , partitionEithers
226226 , partition
227227
228+ -- * Merging streams
229+ -- $merging
230+
231+ , merge
232+ , mergeOn
233+ , mergeBy
234+
228235 -- * Maybes
229236 -- $maybes
230237 , catMaybes
@@ -276,6 +283,7 @@ import Data.Functor.Compose
276283import Data.Functor.Of
277284import qualified Data.Set as Set
278285import qualified Data.IntSet as IntSet
286+ import Data.Ord (Ordering (.. ), comparing )
279287
280288-- instance (Eq a) => Eq1 (Of a) where eq1 = (==)
281289-- instance (Ord a) => Ord1 (Of a) where compare1 = compare
@@ -2719,6 +2727,72 @@ unzip = loop where
27192727
27202728
27212729
2730+ {- $merging
2731+ These functions combine two sorted streams of orderable elements
2732+ into one sorted stream. The elements of the merged stream are
2733+ guaranteed to be in a sorted order if the two input streams are
2734+ also sorted.
2735+
2736+ The merge operation is /left-biased/: when merging two elements
2737+ that compare as equal, the left element is chosen first.
2738+ -}
2739+
2740+ {- | Merge two streams of elements ordered with their 'Ord' instance.
2741+
2742+ The return values of both streams are returned.
2743+
2744+ >>> S.print $ merge (each [1,3,5]) (each [2,4])
2745+ 1
2746+ 2
2747+ 3
2748+ 4
2749+ 5
2750+ ((), ())
2751+
2752+ -}
2753+ merge :: (Monad m , Ord a )
2754+ => Stream (Of a ) m r
2755+ -> Stream (Of a ) m s
2756+ -> Stream (Of a ) m (r , s )
2757+ merge = mergeBy compare
2758+ {-# INLINE merge #-}
2759+
2760+ {- | Merge two streams, ordering them by applying the given function to
2761+ each element before comparing.
2762+
2763+ The return values of both streams are returned.
2764+ -}
2765+ mergeOn :: (Monad m , Ord b )
2766+ => (a -> b )
2767+ -> Stream (Of a ) m r
2768+ -> Stream (Of a ) m s
2769+ -> Stream (Of a ) m (r , s )
2770+ mergeOn f = mergeBy (comparing f)
2771+ {-# INLINE mergeOn #-}
2772+
2773+ {- | Merge two streams, ordering the elements using the given comparison function.
2774+
2775+ The return values of both streams are returned.
2776+ -}
2777+ mergeBy :: Monad m
2778+ => (a -> a -> Ordering )
2779+ -> Stream (Of a ) m r
2780+ -> Stream (Of a ) m s
2781+ -> Stream (Of a ) m (r , s )
2782+ mergeBy cmp = loop
2783+ where
2784+ loop str0 str1 = case str0 of
2785+ Return r0 -> (\ r1 -> (r0, r1)) <$> str1
2786+ Effect m -> Effect $ fmap (\ str -> loop str str1) m
2787+ Step (a :> rest0) -> case str1 of
2788+ Return r1 -> (\ r0 -> (r0, r1)) <$> str0
2789+ Effect m -> Effect $ fmap (loop str0) m
2790+ Step (b :> rest1) -> case cmp a b of
2791+ LT -> Step (a :> loop rest0 str1)
2792+ EQ -> Step (a :> loop rest0 str1) -- left-biased
2793+ GT -> Step (b :> loop str0 rest1)
2794+ {-# INLINABLE mergeBy #-}
2795+
27222796{- $maybes
27232797 These functions discard the 'Nothing's that they encounter. They are analogous
27242798 to the functions from @Data.Maybe@ that share their names.
0 commit comments