From b87cd0a95a29981a9db48fea855e6f17557ff6b7 Mon Sep 17 00:00:00 2001 From: Jack Kelly Date: Tue, 12 Sep 2023 18:45:57 +1000 Subject: [PATCH 1/7] Replace `ConduitM` with `ConduitT` --- src/Streaming/Conduit.hs | 12 ++++++------ streaming-conduit.cabal | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Streaming/Conduit.hs b/src/Streaming/Conduit.hs index f21012e..9659900 100644 --- a/src/Streaming/Conduit.hs +++ b/src/Streaming/Conduit.hs @@ -18,7 +18,7 @@ No 'B.ByteString'-based analogues of 'asConduit' and 'asStream' are provided as it would be of strictly less utility, requiring both the - input and output of the 'ConduitM' to be 'ByteString'. + input and output of the 'ConduitT' to be 'ByteString'. -} module Streaming.Conduit @@ -43,7 +43,7 @@ import Control.Monad (join, void) import Control.Monad.Trans.Class (lift) import Data.ByteString (ByteString) import qualified Data.ByteString.Streaming as B -import Data.Conduit (Conduit, ConduitM, Producer, Source, Consumer, +import Data.Conduit (Conduit, ConduitT, Producer, Source, Consumer, await, runConduit, transPipe, (.|)) import qualified Data.Conduit.List as CL import Streaming (Of, Stream) @@ -53,7 +53,7 @@ import qualified Streaming.Prelude as S -- | The result of this is slightly generic than a 'Source' or a -- 'Producer'. Subject to fusion. -fromStream :: (Monad m) => Stream (Of o) m r -> ConduitM i o m r +fromStream :: (Monad m) => Stream (Of o) m r -> ConduitT i o m r fromStream = CL.unfoldEitherM S.next -- | A type-specialised variant of 'fromStream' that ignores the @@ -67,7 +67,7 @@ fromStreamProducer :: (Monad m) => Stream (Of a) m r -> Producer m a fromStreamProducer = CL.unfoldM S.uncons . void -- | Convert a streaming 'B.ByteString' into a 'Source'; subject to fusion. -fromBStream :: (Monad m) => B.ByteString m r -> ConduitM i ByteString m r +fromBStream :: (Monad m) => B.ByteString m r -> ConduitT i ByteString m r fromBStream = CL.unfoldEitherM B.nextChunk -- | A more specialised variant of 'fromBStream'. @@ -76,7 +76,7 @@ fromBStreamProducer = CL.unfoldEitherM B.unconsChunk . void -- | Convert a 'Producer' to a 'Stream'. Subject to fusion. -- --- It is not possible to generalise this to be a 'ConduitM' as input +-- It is not possible to generalise this to be a 'ConduitT' as input -- values are required. If you need such functionality, see -- 'asStream'. toStream :: (Monad m) => Producer m o -> Stream (Of o) m () @@ -104,7 +104,7 @@ sinkBStream cns stream = runConduit (fromBStream stream .| cns) -- | Treat a function between 'Stream's as a 'Conduit'. May be -- subject to fusion. -asConduit :: (Monad m) => (Stream (Of i) m () -> Stream (Of o) m r) -> ConduitM i o m r +asConduit :: (Monad m) => (Stream (Of i) m () -> Stream (Of o) m r) -> ConduitT i o m r asConduit f = join . fmap (fromStream . f) $ go where -- Probably not the best way to go about it, but it works. diff --git a/streaming-conduit.cabal b/streaming-conduit.cabal index af3f795..32c87e4 100644 --- a/streaming-conduit.cabal +++ b/streaming-conduit.cabal @@ -21,7 +21,7 @@ library exposed-modules: Streaming.Conduit build-depends: base >=4.6 && <5 , bytestring - , conduit >= 1.2.11 && < 1.4 + , conduit >= 1.3.0 && < 1.4 , streaming >= 0.1.3.0 && < 0.3 , streaming-bytestring >= 0.3 && < 0.4 , transformers >= 0.2 From 43e171b47d3536a29671e0397be340ed75f43c29 Mon Sep 17 00:00:00 2001 From: Jack Kelly Date: Tue, 12 Sep 2023 18:52:06 +1000 Subject: [PATCH 2/7] Remove some deprecated aliases so that simplified subsumption works --- ChangeLog.md | 4 ++++ src/Streaming/Conduit.hs | 27 +++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 564c5fc..ffef40e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,9 @@ # Revision history for streaming-conduit +## Unreleased (Minor) -- YYYY-MM-DD + +* Support GHC 9.0. + ## 0.1.3.0 -- 2023-05-13 * Support `streaming-bytestring-0.3` diff --git a/src/Streaming/Conduit.hs b/src/Streaming/Conduit.hs index 9659900..e0bbece 100644 --- a/src/Streaming/Conduit.hs +++ b/src/Streaming/Conduit.hs @@ -43,7 +43,7 @@ import Control.Monad (join, void) import Control.Monad.Trans.Class (lift) import Data.ByteString (ByteString) import qualified Data.ByteString.Streaming as B -import Data.Conduit (Conduit, ConduitT, Producer, Source, Consumer, +import Data.Conduit (Conduit, ConduitT, Producer, Consumer, await, runConduit, transPipe, (.|)) import qualified Data.Conduit.List as CL import Streaming (Of, Stream) @@ -58,21 +58,36 @@ fromStream = CL.unfoldEitherM S.next -- | A type-specialised variant of 'fromStream' that ignores the -- result. -fromStreamSource :: (Monad m) => Stream (Of a) m r -> Source m a +-- +-- It can return a Conduit @Source@: +-- @ +-- fromStreamSource :: (Monad m) => Stream (Of o) m r -> Source m o +-- @ +fromStreamSource :: (Monad m) => Stream (Of o) m r -> ConduitT () o m () fromStreamSource = void . fromStream -- | A more specialised variant of 'fromStream' that is subject to -- fusion. -fromStreamProducer :: (Monad m) => Stream (Of a) m r -> Producer m a -fromStreamProducer = CL.unfoldM S.uncons . void +-- +-- It can return a Conduit @Producer@: +-- @ +-- fromStreamProducer :: (Monad m) => Stream (Of a) m r -> Producer m a +-- @ +fromStreamProducer :: (Monad m) => Stream (Of o) m r -> ConduitT i o m r +fromStreamProducer = CL.unfoldEitherM S.next -- | Convert a streaming 'B.ByteString' into a 'Source'; subject to fusion. fromBStream :: (Monad m) => B.ByteString m r -> ConduitT i ByteString m r fromBStream = CL.unfoldEitherM B.nextChunk -- | A more specialised variant of 'fromBStream'. -fromBStreamProducer :: (Monad m) => B.ByteString m r -> Producer m ByteString -fromBStreamProducer = CL.unfoldEitherM B.unconsChunk . void +-- +-- It can return a Conduit @Producer@: +-- @ +-- fromBStreamProducer :: (Monad m) => B.ByteString m r -> Producer m ByteString +-- @ +fromBStreamProducer :: (Monad m) => B.ByteString m r -> ConduitT i ByteString m r +fromBStreamProducer = CL.unfoldEitherM B.unconsChunk -- | Convert a 'Producer' to a 'Stream'. Subject to fusion. -- From 1b224ac4175ae7b41ee46a570e8d3afc87b0df97 Mon Sep 17 00:00:00 2001 From: Jack Kelly Date: Tue, 12 Sep 2023 18:53:52 +1000 Subject: [PATCH 3/7] Replace deprecated `streaming-bytestring` names --- src/Streaming/Conduit.hs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Streaming/Conduit.hs b/src/Streaming/Conduit.hs index e0bbece..c03876f 100644 --- a/src/Streaming/Conduit.hs +++ b/src/Streaming/Conduit.hs @@ -42,11 +42,12 @@ module Streaming.Conduit import Control.Monad (join, void) import Control.Monad.Trans.Class (lift) import Data.ByteString (ByteString) -import qualified Data.ByteString.Streaming as B import Data.Conduit (Conduit, ConduitT, Producer, Consumer, await, runConduit, transPipe, (.|)) import qualified Data.Conduit.List as CL import Streaming (Of, Stream) +import Streaming.ByteString (ByteStream) +import qualified Streaming.ByteString as B import qualified Streaming.Prelude as S -------------------------------------------------------------------------------- @@ -77,16 +78,16 @@ fromStreamProducer :: (Monad m) => Stream (Of o) m r -> ConduitT i o m r fromStreamProducer = CL.unfoldEitherM S.next -- | Convert a streaming 'B.ByteString' into a 'Source'; subject to fusion. -fromBStream :: (Monad m) => B.ByteString m r -> ConduitT i ByteString m r -fromBStream = CL.unfoldEitherM B.nextChunk +fromBStream :: (Monad m) => ByteStream m r -> ConduitT i ByteString m r +fromBStream = CL.unfoldEitherM B.unconsChunk -- | A more specialised variant of 'fromBStream'. -- -- It can return a Conduit @Producer@: -- @ --- fromBStreamProducer :: (Monad m) => B.ByteString m r -> Producer m ByteString +-- fromBStreamProducer :: (Monad m) => ByteStream m r -> Producer m ByteString -- @ -fromBStreamProducer :: (Monad m) => B.ByteString m r -> ConduitT i ByteString m r +fromBStreamProducer :: (Monad m) => ByteStream m r -> ConduitT i ByteString m r fromBStreamProducer = CL.unfoldEitherM B.unconsChunk -- | Convert a 'Producer' to a 'Stream'. Subject to fusion. @@ -97,9 +98,9 @@ fromBStreamProducer = CL.unfoldEitherM B.unconsChunk toStream :: (Monad m) => Producer m o -> Stream (Of o) m () toStream cnd = runConduit (transPipe lift cnd .| CL.mapM_ S.yield) --- | Convert a 'Producer' to a 'B.ByteString' stream. Subject to +-- | Convert a 'Producer' to a 'ByteStream' stream. Subject to -- fusion. -toBStream :: (Monad m) => Producer m ByteString -> B.ByteString m () +toBStream :: (Monad m) => Producer m ByteString -> ByteStream m () toBStream cnd = runConduit (transPipe lift cnd .| CL.mapM_ B.chunk) -- | Treat a 'Conduit' as a function between 'Stream's. Subject to @@ -112,9 +113,9 @@ asStream cnd stream = toStream (fromStream stream .| cnd) sinkStream :: (Monad m) => Consumer i m r -> Stream (Of i) m () -> m r sinkStream cns stream = runConduit (fromStream stream .| cns) --- | Treat a 'Consumer' as a function which consumes a 'B.ByteString'. +-- | Treat a 'Consumer' as a function which consumes a 'ByteStream'. -- Subject to fusion. -sinkBStream :: (Monad m) => Consumer ByteString m r -> B.ByteString m () -> m r +sinkBStream :: (Monad m) => Consumer ByteString m r -> ByteStream m () -> m r sinkBStream cns stream = runConduit (fromBStream stream .| cns) -- | Treat a function between 'Stream's as a 'Conduit'. May be From 600d0779f81aff66bf26331f1da7f0a59775bae8 Mon Sep 17 00:00:00 2001 From: Jack Kelly Date: Tue, 12 Sep 2023 18:54:55 +1000 Subject: [PATCH 4/7] Remove GHC-7 claims `streaming-bytestring-0.3.0` removes support for GHC 7 anyway, so no point us claiming compatibility with `base >= 4.6` --- streaming-conduit.cabal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/streaming-conduit.cabal b/streaming-conduit.cabal index 32c87e4..69cbdad 100644 --- a/streaming-conduit.cabal +++ b/streaming-conduit.cabal @@ -11,7 +11,7 @@ category: Data, Streaming build-type: Simple extra-source-files: ChangeLog.md, README.md cabal-version: >=1.10 -tested-with: GHC == 7.10.2, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.3.* +tested-with: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.3.*, GHC == 9.0.2, GHC == 9.2.4 source-repository head type: git @@ -19,7 +19,7 @@ source-repository head library exposed-modules: Streaming.Conduit - build-depends: base >=4.6 && <5 + build-depends: base >=4.9 && <5 , bytestring , conduit >= 1.3.0 && < 1.4 , streaming >= 0.1.3.0 && < 0.3 From d9c8ecca6ce35a60c3183ea37e73ae00e30b86dc Mon Sep 17 00:00:00 2001 From: Jack Kelly Date: Tue, 12 Sep 2023 19:02:43 +1000 Subject: [PATCH 5/7] Remove deprecated `Conduit`/`Producer`/`Consumer` type aliases --- ChangeLog.md | 1 + src/Streaming/Conduit.hs | 35 +++++++++++++++++++++++++++-------- streaming-conduit.cabal | 2 +- test/conversions.hs | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index ffef40e..e8b1520 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,7 @@ ## Unreleased (Minor) -- YYYY-MM-DD +* Stop referring to deprecated names in `conduit` and `streaming-bytestring`. * Support GHC 9.0. ## 0.1.3.0 -- 2023-05-13 diff --git a/src/Streaming/Conduit.hs b/src/Streaming/Conduit.hs index c03876f..bf49e21 100644 --- a/src/Streaming/Conduit.hs +++ b/src/Streaming/Conduit.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE RankNTypes #-} - {- | Module : Streaming.Conduit Description : Bidirectional support for the streaming and conduit libraries @@ -42,9 +40,10 @@ module Streaming.Conduit import Control.Monad (join, void) import Control.Monad.Trans.Class (lift) import Data.ByteString (ByteString) -import Data.Conduit (Conduit, ConduitT, Producer, Consumer, +import Data.Conduit (ConduitT, await, runConduit, transPipe, (.|)) import qualified Data.Conduit.List as CL +import Data.Void (Void) import Streaming (Of, Stream) import Streaming.ByteString (ByteStream) import qualified Streaming.ByteString as B @@ -95,27 +94,47 @@ fromBStreamProducer = CL.unfoldEitherM B.unconsChunk -- It is not possible to generalise this to be a 'ConduitT' as input -- values are required. If you need such functionality, see -- 'asStream'. -toStream :: (Monad m) => Producer m o -> Stream (Of o) m () +-- +-- It can accept a Conduit @Producer@: +-- @ +-- toStream :: (Monad m) => Producer m o -> Stream (Of o) m () +-- @ +toStream :: (Monad m) => ConduitT () o m () -> Stream (Of o) m () toStream cnd = runConduit (transPipe lift cnd .| CL.mapM_ S.yield) -- | Convert a 'Producer' to a 'ByteStream' stream. Subject to -- fusion. -toBStream :: (Monad m) => Producer m ByteString -> ByteStream m () +-- +-- It can accept a Conduit @Producer@: +-- @ +-- toBStream :: (Monad m) => Producer m ByteString -> ByteStream m () +-- @ +toBStream :: (Monad m) => ConduitT () ByteString m () -> ByteStream m () toBStream cnd = runConduit (transPipe lift cnd .| CL.mapM_ B.chunk) -- | Treat a 'Conduit' as a function between 'Stream's. Subject to -- fusion. -asStream :: (Monad m) => Conduit i m o -> Stream (Of i) m () -> Stream (Of o) m () +asStream :: (Monad m) => ConduitT i o m () -> Stream (Of i) m () -> Stream (Of o) m () asStream cnd stream = toStream (fromStream stream .| cnd) -- | Treat a 'Consumer' as a function which consumes a 'Stream'. -- Subject to fusion. -sinkStream :: (Monad m) => Consumer i m r -> Stream (Of i) m () -> m r +-- +-- It can accept a Conduit @Consumer@: +-- @ +-- sinkStream :: (Monad m) => Consumer i m r -> Stream (Of i) m () -> m r +-- @ +sinkStream :: (Monad m) => ConduitT i Void m r -> Stream (Of i) m () -> m r sinkStream cns stream = runConduit (fromStream stream .| cns) -- | Treat a 'Consumer' as a function which consumes a 'ByteStream'. -- Subject to fusion. -sinkBStream :: (Monad m) => Consumer ByteString m r -> ByteStream m () -> m r +-- +-- It can accept a Conduit @Consumer@: +-- @ +-- sinkBStream :: (Monad m) => Consumer ByteString m r -> ByteStream m () -> m r +-- @ +sinkBStream :: (Monad m) => ConduitT ByteString Void m r -> ByteStream m () -> m r sinkBStream cns stream = runConduit (fromBStream stream .| cns) -- | Treat a function between 'Stream's as a 'Conduit'. May be diff --git a/streaming-conduit.cabal b/streaming-conduit.cabal index 69cbdad..baf1ab5 100644 --- a/streaming-conduit.cabal +++ b/streaming-conduit.cabal @@ -34,7 +34,7 @@ test-suite conversions build-depends: streaming-conduit , base , conduit - , hspec == 2.4.* + , hspec >= 2.8.0 && < 2.12 , streaming hs-source-dirs: test default-language: Haskell2010 diff --git a/test/conversions.hs b/test/conversions.hs index d22008e..c05fec8 100644 --- a/test/conversions.hs +++ b/test/conversions.hs @@ -43,7 +43,7 @@ main = hspec $ do prop "sinkStream" $ testPipeline (\xs f -> runIdentity $ sinkStream C.consume $ S.map f $ S.each xs) -conduitList :: C.Source Identity a -> [a] +conduitList :: C.ConduitT () a Identity () -> [a] conduitList = runIdentity . C.sourceToList streamList :: S.Stream (S.Of a) Identity () -> [a] From 5b02ac1a3c7356d9f41f72fb47f5b91c0ba1e0b3 Mon Sep 17 00:00:00 2001 From: Jack Kelly Date: Tue, 12 Sep 2023 19:09:07 +1000 Subject: [PATCH 6/7] Generalise return type of `toStream` and `toBStream` This also breaks the direct dependency on `transformers`. --- ChangeLog.md | 11 +++++++++++ src/Streaming/Conduit.hs | 26 +++++++++++++++++++------- streaming-conduit.cabal | 1 - 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index e8b1520..11b5f10 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,17 @@ ## Unreleased (Minor) -- YYYY-MM-DD +* Generalise the return types of `toStream` and `toBStream` to return + the conduit's return type: + + ``` + Old: toStream :: (Monad m) => ConduitT () o m () -> Stream (Of o) m () + New: toStream :: (Monad m) => ConduitT () o m r -> Stream (Of o) m r + + Old: toBStream :: (Monad m) => ConduitT () ByteString m () -> ByteStream m () + New: toBStream :: (Monad m) => ConduitT () ByteString m r -> ByteStream m r + ``` + * Stop referring to deprecated names in `conduit` and `streaming-bytestring`. * Support GHC 9.0. diff --git a/src/Streaming/Conduit.hs b/src/Streaming/Conduit.hs index bf49e21..7574df8 100644 --- a/src/Streaming/Conduit.hs +++ b/src/Streaming/Conduit.hs @@ -38,13 +38,13 @@ module Streaming.Conduit ) where import Control.Monad (join, void) -import Control.Monad.Trans.Class (lift) import Data.ByteString (ByteString) -import Data.Conduit (ConduitT, - await, runConduit, transPipe, (.|)) +import Data.Conduit (await, runConduit, (.|)) +import Data.Conduit.Internal (ConduitT(..), Pipe(..)) import qualified Data.Conduit.List as CL import Data.Void (Void) import Streaming (Of, Stream) +import qualified Streaming as S import Streaming.ByteString (ByteStream) import qualified Streaming.ByteString as B import qualified Streaming.Prelude as S @@ -99,8 +99,14 @@ fromBStreamProducer = CL.unfoldEitherM B.unconsChunk -- @ -- toStream :: (Monad m) => Producer m o -> Stream (Of o) m () -- @ -toStream :: (Monad m) => ConduitT () o m () -> Stream (Of o) m () -toStream cnd = runConduit (transPipe lift cnd .| CL.mapM_ S.yield) +toStream :: (Monad m) => ConduitT () o m r -> Stream (Of o) m r +toStream (ConduitT k) = go $ k Done + where + go (HaveOutput p o) = S.yield o *> go p + go (NeedInput _ c) = go $ c () + go (Done r) = pure r + go (PipeM mp) = S.effect $ go <$> mp + go (Leftover p _) = go p -- | Convert a 'Producer' to a 'ByteStream' stream. Subject to -- fusion. @@ -109,8 +115,14 @@ toStream cnd = runConduit (transPipe lift cnd .| CL.mapM_ S.yield) -- @ -- toBStream :: (Monad m) => Producer m ByteString -> ByteStream m () -- @ -toBStream :: (Monad m) => ConduitT () ByteString m () -> ByteStream m () -toBStream cnd = runConduit (transPipe lift cnd .| CL.mapM_ B.chunk) +toBStream :: (Monad m) => ConduitT () ByteString m r -> ByteStream m r +toBStream (ConduitT k) = go $ k Done + where + go (HaveOutput p o) = B.fromStrict o *> go p + go (NeedInput _ c) = go $ c () + go (Done r) = pure r + go (PipeM mp) = B.mwrap $ go <$> mp + go (Leftover p _) = go p -- | Treat a 'Conduit' as a function between 'Stream's. Subject to -- fusion. diff --git a/streaming-conduit.cabal b/streaming-conduit.cabal index baf1ab5..9588a79 100644 --- a/streaming-conduit.cabal +++ b/streaming-conduit.cabal @@ -24,7 +24,6 @@ library , conduit >= 1.3.0 && < 1.4 , streaming >= 0.1.3.0 && < 0.3 , streaming-bytestring >= 0.3 && < 0.4 - , transformers >= 0.2 hs-source-dirs: src default-language: Haskell2010 From b4fb8e33189b9498cd13bd9712b540fb68ad9840 Mon Sep 17 00:00:00 2001 From: Jack Kelly Date: Tue, 12 Sep 2023 19:09:38 +1000 Subject: [PATCH 7/7] Move `void` import to `Data.Functor` --- src/Streaming/Conduit.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Streaming/Conduit.hs b/src/Streaming/Conduit.hs index 7574df8..2f6dd69 100644 --- a/src/Streaming/Conduit.hs +++ b/src/Streaming/Conduit.hs @@ -37,11 +37,12 @@ module Streaming.Conduit , sinkBStream ) where -import Control.Monad (join, void) +import Control.Monad (join) import Data.ByteString (ByteString) import Data.Conduit (await, runConduit, (.|)) import Data.Conduit.Internal (ConduitT(..), Pipe(..)) import qualified Data.Conduit.List as CL +import Data.Functor (void) import Data.Void (Void) import Streaming (Of, Stream) import qualified Streaming as S