packages feed

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 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+=================++[![Hackage](https://img.shields.io/hackage/v/streaming-conduit.svg)](https://hackage.haskell.org/package/streaming-conduit) [![Build Status](https://travis-ci.org/ivan-m/streaming-conduit.svg)](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)