@@ -147,6 +147,7 @@ module Streamly.Streams.StreamD
147147 , interleaveMin
148148 , interleaveFst
149149 , roundRobin -- interleaveFair?/ParallelFair
150+ , interleaveFstThenConcat
150151
151152 -- ** Grouping
152153 , groupsOf
@@ -2025,6 +2026,89 @@ roundRobin (Stream step1 state1) (Stream step2 state2) =
20252026 Skip s -> Skip (InterleaveFirstOnly s)
20262027 Stop -> Stop
20272028
2029+data ICUState s1 s2 i1 i2 =
2030+ ICUFirst s1 s2
2031+ | ICUSecond s1 s2
2032+ | ICUSecondOnly s2
2033+ | ICUFirstOnly s1
2034+ | ICUFirstInner s1 s2 i1
2035+ | ICUSecondInner s1 s2 i2
2036+ | ICUFirstOnlyInner s1 i1
2037+ | ICUSecondOnlyInner s2 i2
2038+
2039+-- | Interleave streams (full streams, not the elements) unfolded from two
2040+-- input streams and concat. Stop when the first stream stops. If the second
2041+-- stream ends before the first one then first stream still keeps running alone
2042+-- without any interleaving with the second stream.
2043+--
2044+-- [a1, a2, ... an] [b1, b2 ...]
2045+-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2046+-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2047+-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2048+--
2049+{-# INLINE_NORMAL interleaveFstThenConcat #-}
2050+interleaveFstThenConcat
2051+ :: Monad m
2052+ => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2053+interleaveFstThenConcat
2054+ (Unfold istep1 inject1) (Stream step1 state1)
2055+ (Unfold istep2 inject2) (Stream step2 state2) =
2056+ Stream step (ICUFirst state1 state2)
2057+
2058+ where
2059+
2060+ {-# INLINE_LATE step #-}
2061+ step gst (ICUFirst s1 s2) = do
2062+ r <- step1 (adaptState gst) s1
2063+ case r of
2064+ Yield a s -> do
2065+ i <- inject1 a
2066+ i `seq` return (Skip (ICUFirstInner s s2 i))
2067+ Skip s -> return $ Skip (ICUFirst s s2)
2068+ Stop -> return Stop
2069+
2070+ step gst (ICUFirstOnly s1) = do
2071+ r <- step1 (adaptState gst) s1
2072+ case r of
2073+ Yield a s -> do
2074+ i <- inject1 a
2075+ i `seq` return (Skip (ICUFirstOnlyInner s i))
2076+ Skip s -> return $ Skip (ICUFirstOnly s)
2077+ Stop -> return Stop
2078+
2079+ step _ (ICUFirstInner s1 s2 i1) = do
2080+ r <- istep1 i1
2081+ return $ case r of
2082+ Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
2083+ Skip i' -> Skip (ICUFirstInner s1 s2 i')
2084+ Stop -> Skip (ICUSecond s1 s2)
2085+
2086+ step _ (ICUFirstOnlyInner s1 i1) = do
2087+ r <- istep1 i1
2088+ return $ case r of
2089+ Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
2090+ Skip i' -> Skip (ICUFirstOnlyInner s1 i')
2091+ Stop -> Skip (ICUFirstOnly s1)
2092+
2093+ step gst (ICUSecond s1 s2) = do
2094+ r <- step2 (adaptState gst) s2
2095+ case r of
2096+ Yield a s -> do
2097+ i <- inject2 a
2098+ i `seq` return (Skip (ICUSecondInner s1 s i))
2099+ Skip s -> return $ Skip (ICUSecond s1 s)
2100+ Stop -> return $ Skip (ICUFirstOnly s1)
2101+
2102+ step _ (ICUSecondInner s1 s2 i2) = do
2103+ r <- istep2 i2
2104+ return $ case r of
2105+ Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
2106+ Skip i' -> Skip (ICUSecondInner s1 s2 i')
2107+ Stop -> Skip (ICUFirst s1 s2)
2108+
2109+ step _ (ICUSecondOnly _s2) = undefined
2110+ step _ (ICUSecondOnlyInner _s2 _i2) = undefined
2111+
20282112------------------------------------------------------------------------------
20292113-- Exceptions
20302114------------------------------------------------------------------------------