streaming-conduit (empty) → 0.1.0.0
raw patch · 7 files changed
+230/−0 lines, 7 filesdep +basedep +conduitdep +hspecsetup-changed
Dependencies added: base, conduit, hspec, streaming, streaming-conduit, transformers
Files
- ChangeLog.md +5/−0
- LICENSE +20/−0
- README.md +25/−0
- Setup.hs +2/−0
- src/Streaming/Conduit.hs +86/−0
- streaming-conduit.cabal +38/−0
- test/conversions.hs +54/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for streaming-conduit++## 0.1.0.0 -- 2017-06-08++* Initial release
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2017 Ivan Lazar Miljenovic++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,25 @@+streaming-conduit+=================++[](https://hackage.haskell.org/package/streaming-conduit) [](https://travis-ci.org/ivan-m/streaming-conduit)++Bidirectional support between the [streaming] and [conduit] libraries.++[streaming]: http://hackage.haskell.org/package/streaming+[conduit]: http://hackage.haskell.org/package/conduit++Motivation+----------++The streaming library provides a rather elegant model of how to stream+data, with libraries providing support for features like+[`ByteString`s], [PostgreSQL], [network requests] and others.++[`ByteString`s]: http://hackage.haskell.org/package/streaming-bytestring+[PostgreSQL]: http://hackage.haskell.org/package/streaming-postgresql-simple+[network requests]: http://hackage.haskell.org/package/streaming-wai++However, there are various other libraries you may wish to use that+represent data streaming as a `Conduit`.++This library provides support to convert between these two models.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Streaming/Conduit.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE RankNTypes #-}++{- |+ Module : Streaming.Conduit+ Description : Bidirectional support for the streaming and conduit libraries+ Copyright : Ivan Lazar Miljenovic+ License : MIT+ Maintainer : Ivan.Miljenovic@gmail.com+++ This provides interoperability between the+ <http://hackage.haskell.org/package/streaming streaming> and+ <http://hackage.haskell.org/package/conduit conduit> libraries.++ Not only can you convert between one streaming data representation+ to the other, there is also support to use one in the middle of a+ pipeline.++ -}+module Streaming.Conduit+ ( -- * Converting from Streams+ fromStream+ , fromStreamSource+ , fromStreamProducer+ , asConduit+ -- * Converting from Conduits+ , toStream+ , asStream+ ) where++import Control.Monad (join, void)+import Control.Monad.Trans.Class (lift)+import Data.Conduit (Conduit, ConduitM, Producer, Source,+ await, runConduit, yield, (.|))+import qualified Data.Conduit.List as CL+import Streaming (Of, Stream, hoist, lazily,+ streamFold)+import qualified Streaming.Prelude as S++--------------------------------------------------------------------------------++-- | The result of this is slightly generic than a 'Source' or a+-- 'Producer'. If it fits in the types you want, you may wish to use+-- 'fromStreamProducer' which is subject to fusion.+fromStream :: (Monad m) => Stream (Of o) m r -> ConduitM i o m r+fromStream = streamFold return (join . lift) (uncurry ((>>) . yield) . lazily)++-- | A type-specialised variant of 'fromStream' that ignores the+-- result.+fromStreamSource :: (Monad m) => Stream (Of a) m r -> Source m a+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++-- | Convert a 'Source' to a 'Stream'. Subject to fusion.+--+-- It is not possible to generalise this to be a 'ConduitM' as input+-- values are required. If you need such functionality, see+-- 'asStream'.+toStream :: (Monad m) => Producer m o -> Stream (Of o) m ()+toStream cnd = runConduit (cnd' .| mkStream)+ where+ mkStream = CL.mapM_ S.yield++ cnd' = hoist lift cnd++-- | 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 cnd stream = toStream (src .| cnd)+ where+ src = fromStreamProducer stream++-- | 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) -> Conduit i m o+asConduit f = join . fmap (fromStreamProducer . f) $ go+ where+ -- Probably not the best way to go about it, but it works.+ go = do mo <- await+ case mo of+ Nothing -> return (return ())+ Just o -> S.cons o <$> go
+ streaming-conduit.cabal view
@@ -0,0 +1,38 @@+name: streaming-conduit+version: 0.1.0.0+synopsis: Bidirectional support between the streaming and conduit libraries+description: Allow interoperability between the streaming and conduit data streaming ecosystems.+license: MIT+license-file: LICENSE+author: Ivan Lazar Miljenovic+maintainer: Ivan.Miljenovic@gmail.com+copyright: Ivan Lazar Miljenovic+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.1.*++source-repository head+ type: git+ location: https://github.com/ivan-m/streaming-conduit.git++library+ exposed-modules: Streaming.Conduit+ build-depends: base >=4.6 && <5+ , conduit >= 1.2.1 && < 1.3+ , streaming >= 0.1.3.0 && < 0.2+ , transformers >= 0.2+ hs-source-dirs: src+ default-language: Haskell2010++test-suite conversions+ type: exitcode-stdio-1.0+ main-is: conversions.hs+ build-depends: streaming-conduit+ , base+ , conduit+ , hspec == 2.4.*+ , streaming+ hs-source-dirs: test+ default-language: Haskell2010
+ test/conversions.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE RankNTypes #-}+{- |+ Module : Main+ Description : Basic conversion tests+ Copyright : Ivan Lazar Miljenovic+ License : MIT+ Maintainer : Ivan.Miljenovic@gmail.com++++ -}+module Main (main) where++import Streaming.Conduit++import qualified Data.Conduit as C+import qualified Data.Conduit.List as C+import qualified Streaming as S+import qualified Streaming.Prelude as S++import Test.Hspec+import Test.Hspec.QuickCheck++import Data.Functor.Identity (Identity, runIdentity)++--------------------------------------------------------------------------------++main :: IO ()+main = hspec $ do+ describe "Stream -> Conduit" $ do+ prop "fromStream" $+ testPipeline (\xs f -> conduitList (fromStream (S.each xs) C..| C.map f))+ prop "fromStreamProducer" $+ testPipeline (\xs f -> conduitList (fromStreamProducer (S.each xs) C..| C.map f))+ prop "asConduit" $+ testPipeline (\xs f -> conduitList (C.sourceList xs C..| asConduit (S.map f)))++ describe "Conduit -> Stream" $ do+ prop "toStream" $+ testPipeline (\xs f -> streamList . S.map f $ toStream (C.sourceList xs))+ prop "asStream" $+ testPipeline (\xs f -> streamList . asStream (C.map f) $ S.each xs)++conduitList :: C.Source Identity a -> [a]+conduitList = runIdentity . C.sourceToList++streamList :: S.Stream (S.Of a) Identity () -> [a]+streamList = runIdentity . S.toList_++testPipeline :: (forall a. [a] -> (a -> a) -> [a]) -> [Int] -> Bool+testPipeline pipeline xs = pipeline xs plusOne == map plusOne xs++plusOne :: Int -> Int+plusOne = (+1)