diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2015 Michael Thompson, 2012-2014 Gabriel Gonzalez
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of michaelt nor the names of other contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Streaming.hs b/Streaming.hs
new file mode 100644
--- /dev/null
+++ b/Streaming.hs
@@ -0,0 +1,48 @@
+{-#LANGUAGE RankNTypes #-}
+module Streaming 
+   (
+   -- * Constructing a 'Stream' on a base functor
+   construct,
+   unfold,
+   for,
+   -- * Transforming streams
+   maps,
+   maps',
+   mapsM,
+   
+   -- * Inspecting a stream
+   inspect,
+   
+   -- * Eliminating a 'Stream'
+   destroy,
+   intercalates,
+   concats,
+   iterTM,
+   iterT,
+
+   -- * Splitting and joining 'Stream's 
+   split,
+   chunksOf,
+   concats,
+
+   -- * Types
+   Stream,
+   Of (..),
+   lazily,
+   strictly,
+   
+   -- * re-exports
+   MFunctor(..),
+   MonadTrans(..)
+   )
+   where
+import Streaming.Internal
+import Streaming.Prelude 
+import Control.Monad.Morph (MFunctor(..))
+import Control.Monad
+import Control.Monad.Trans
+
+
+
+
+
diff --git a/Streaming/Internal.hs b/Streaming/Internal.hs
new file mode 100644
--- /dev/null
+++ b/Streaming/Internal.hs
@@ -0,0 +1,225 @@
+{-# LANGUAGE RankNTypes, StandaloneDeriving,DeriveDataTypeable, BangPatterns #-}
+{-# LANGUAGE UndecidableInstances #-} -- for show, data instances
+module Streaming.Internal where
+
+import Control.Monad
+import Control.Monad.Trans
+import Control.Monad.Trans.Class
+import Control.Applicative
+import Data.Foldable ( Foldable )
+import Data.Traversable
+import Control.Monad.Morph
+import Data.Monoid
+import Data.Functor.Identity
+import GHC.Exts ( build )
+import Data.Data ( Data, Typeable )
+import Prelude hiding (splitAt)
+
+{-| 'Stream' data type is equivalent to @FreeT@ and can represent any effectful
+    succession of steps, where the steps are specified by the first 'functor' parameter. 
+
+> data Stream f m r = Step !(f (Stream f m r)) | Delay (m (Stream f m r)) | Return r
+
+    The /producer/ concept uses the simple functor @ (a,_) @ \- or the stricter 
+    @ Of a _ @. Then the news at each step or layer is just: an individual item of type @a@. 
+    Since @Stream (Of a) m r@ is equivalent to @Pipe.Producer a m r@, much of
+    the @pipes@ @Prelude@ can easily be mirrored in a @streaming@ @Prelude@. Similarly, 
+    a simple @Consumer a m r@ or @Parser a m r@ concept arises when the base functor is
+    @ (a -> _) @ . @Stream ((->) input) m result@ consumes @input@ until it returns a 
+    @result@.
+
+    To avoid breaking reasoning principles, the constructors 
+    should not be used directly. A pattern-match should go by way of 'inspect' \
+    \- or, in the producer case, 'Streaming.Prelude.next'
+    The constructors are exported by the 'Internal' module.
+-}
+data Stream f m r = Step !(f (Stream f m r))
+                  | Delay (m (Stream f m r))
+                  | Return r
+                  deriving (Typeable)
+
+deriving instance (Show r, Show (m (Stream f m r))
+                  , Show (f (Stream f m r))) => Show (Stream f m r)
+deriving instance (Eq r, Eq (m (Stream f m r))
+                  , Eq (f (Stream f m r))) => Eq (Stream f m r)
+deriving instance (Typeable f, Typeable m, Data r, Data (m (Stream f m r))
+                  , Data (f (Stream f m r))) => Data (Stream f m r)
+
+instance (Functor f, Monad m) => Functor (Stream f m) where
+  fmap f = loop where
+    loop stream = case stream of
+      Return r -> Return (f r)
+      Delay m  -> Delay (liftM loop m)
+      Step f   -> Step (fmap loop f)
+  {-# INLINABLE fmap #-}
+  
+instance (Functor f, Monad m) => Monad (Stream f m) where
+  return = Return
+  {-# INLINE return #-}
+  stream1 >> stream2 = loop stream1 where
+    loop stream = case stream of
+      Return _ -> stream2
+      Delay m  -> Delay (liftM loop m)
+      Step f   -> Step (fmap loop f)    
+  {-# INLINABLE (>>) #-}                              
+  stream >>= f = loop stream where
+    loop stream0 = case stream0 of
+      Step f -> Step (fmap loop f)
+      Delay m      -> Delay (liftM loop m)
+      Return r      -> f r
+  {-# INLINABLE (>>=) #-}                              
+
+instance (Functor f, Monad m) => Applicative (Stream f m) where
+  pure = Return
+  {-# INLINE pure #-}
+  streamf <*> streamx = do {f <- streamf; x <- streamx; return (f x)}   
+  {-# INLINABLE (<*>) #-}    
+  
+instance Functor f => MonadTrans (Stream f) where
+  lift = Delay . liftM Return
+  {-# INLINE lift #-}
+
+instance Functor f => MFunctor (Stream f) where
+  hoist trans = loop where
+    loop stream = case stream of 
+      Return r  -> Return r
+      Delay m   -> Delay (trans (liftM loop m))
+      Step f    -> Step (fmap loop f)
+  {-# INLINABLE hoist #-}    
+
+instance (MonadIO m, Functor f) => MonadIO (Stream f m) where
+  liftIO = Delay . liftM Return . liftIO
+  {-# INLINE liftIO #-}
+
+-- | Map a stream to its church encoding; compare list 'foldr'
+destroy 
+  :: (Functor f, Monad m) =>
+     Stream f m r -> (f b -> b) -> (m b -> b) -> (r -> b) -> b
+destroy stream0 construct wrap done = loop stream0 where
+  loop stream = case stream of
+    Return r -> done r
+    Delay m  -> wrap (liftM loop m)
+    Step fs  -> construct (fmap loop fs)
+{-# INLINABLE destroy #-}
+
+-- | Reflect a church-encoded stream; cp. GHC.Exts.build
+construct
+  :: (forall b . (f b -> b) -> (m b -> b) -> (r -> b) -> b) ->  Stream f m r
+construct = \phi -> phi Step Delay Return
+{-# INLINE construct #-}
+
+
+{-| Inspect the first stage of a freely layered sequence. 
+    Compare @Pipes.next@ and the replica @Streaming.Prelude.next@. 
+    This is the 'uncons' for the general 'unfold'.
+
+> unfold inspect = id
+> Streaming.Prelude.unfoldr StreamingPrelude.next = id
+-}
+inspect :: (Functor f, Monad m) =>
+     Stream f m r -> m (Either r (f (Stream f m r)))
+inspect = loop where
+  loop stream = case stream of
+    Return r -> return (Left r)
+    Delay m  -> m >>= loop
+    Step fs  -> return (Right fs)
+{-# INLINABLE inspect #-}
+    
+{-| Build a @Stream@ by unfolding steps starting from a seed. 
+
+> unfold inspect = id -- modulo the quotient we work with
+> unfold Pipes.next :: Monad m => Producer a m r -> Stream ((,) a) m r
+> unfold (curry (:>) . Pipes.next) :: Monad m => Producer a m r -> Stream (Of a) m r
+
+-}
+
+unfold :: (Monad m, Functor f) 
+        => (s -> m (Either r (f s))) -> s -> Stream f m r
+unfold step = loop where
+  loop s0 = Delay $ do 
+    e <- step s0
+    case e of
+      Left r -> return (Return r)
+      Right fs -> return (Step (fmap loop fs))
+{-# INLINABLE unfold #-}
+
+
+-- | Map layers of one functor to another with a natural transformation
+maps :: (Monad m, Functor f) 
+     => (forall x . f x -> g x) -> Stream f m r -> Stream g m r
+maps phi = loop where
+  loop stream = case stream of 
+    Return r  -> Return r
+    Delay m   -> Delay (liftM loop m)
+    Step f    -> Step (phi (fmap loop f))
+{-# INLINABLE maps #-}
+
+-- | Map layers of one functor to another with a transformation involving the base monad
+mapsM :: (Monad m, Functor f) => (forall x . f x -> m (g x)) -> Stream f m r -> Stream g m r
+mapsM phi = loop where
+  loop stream = case stream of 
+    Return r  -> Return r
+    Delay m   -> Delay (liftM loop m)
+    Step f    -> Delay (liftM Step (phi (fmap loop f)))
+{-# INLINABLE mapsM #-}
+
+
+
+
+intercalates :: (Monad m, Monad (t m), MonadTrans t) =>
+     t m a -> Stream (t m) m b -> t m b
+intercalates sep = go0
+  where
+    go0 f = case f of 
+      Return r -> return r 
+      Delay m -> lift m >>= go0 
+      Step fstr -> do
+                f' <- fstr
+                go1 f'
+    go1 f = case f of 
+      Return r -> return r 
+      Delay m     -> lift m >>= go1
+      Step fstr ->  do
+                sep
+                f' <- fstr
+                go1 f'
+{-# INLINABLE intercalates #-}
+
+iterTM ::
+  (Functor f, Monad m, MonadTrans t,
+   Monad (t m)) =>
+  (f (t m a) -> t m a) -> Stream f m a -> t m a
+iterTM out stream = destroy stream out (join . lift) return
+{-# INLINE iterTM #-}
+
+iterT ::
+  (Functor f, Monad m) => (f (m a) -> m a) -> Stream f m a -> m a
+iterT out stream = destroy stream out join return
+{-# INLINE iterT #-}
+
+concats ::
+    (MonadTrans t, Monad (t m), Monad m) =>
+    Stream (t m) m a -> t m a
+concats stream = destroy stream join (join . lift) return
+{-# INLINE concats #-}
+
+
+split :: (Monad m, Functor f) => Int -> Stream f m r -> Stream f m (Stream f m r)
+split = loop where
+  loop !n stream 
+    | n <= 1 = Return stream
+    | otherwise = case stream of
+        Return r       -> Return (Return r)
+        Delay m        -> Delay (liftM (loop n) m)
+        Step fs        -> case n of 
+          0 -> Return (Step fs)
+          _ -> Step (fmap (loop (n-1)) fs)
+{-# INLINABLE split #-}                        
+
+chunksOf :: (Monad m, Functor f) => Int -> Stream f m r -> Stream (Stream f m) m r
+chunksOf n0 = loop where
+  loop stream = case stream of
+    Return r       -> Return r
+    Delay m        -> Delay (liftM loop m)
+    Step fs        -> Step $ Step $ fmap (fmap loop . split n0) fs
+{-# INLINABLE chunksOf #-}          
diff --git a/Streaming/Prelude.hs b/Streaming/Prelude.hs
new file mode 100644
--- /dev/null
+++ b/Streaming/Prelude.hs
@@ -0,0 +1,964 @@
+{-| This module is very closely modeled on Pipes.Prelude
+-}
+{-# LANGUAGE RankNTypes, BangPatterns, DeriveDataTypeable,
+             DeriveFoldable, DeriveFunctor, DeriveTraversable #-}
+             
+module Streaming.Prelude (
+    -- * Types
+    Stream 
+    , Of (..)
+    , lazily
+    , strictly
+    
+    -- * Introducing streams of elements
+    -- $producers
+    , each
+    , yield
+    , unfoldr
+    , stdinLn
+    , readLn
+    , fromHandle
+    , repeatM
+    , replicateM
+
+    -- * Consuming streams of elements
+    -- $consumers
+    , stdoutLn
+    , stdoutLn'
+    , mapM_
+    , print
+    , toHandle
+    , drain
+
+    -- * Stream transformers
+    -- $pipes
+    , map
+    , mapM
+    , maps'
+    , maps
+    , sequence
+    , mapFoldable
+    , filter
+    , filterM
+    , for
+    , take
+    , takeWhile
+--    , takeWhile'
+    , drop
+    , dropWhile
+    , concat
+    -- , elemIndices
+    -- , findIndices
+    , scan
+    , scanM
+    , chain
+    , read
+    , show
+    , seq
+
+    -- * Splitting and inspecting streams of elements
+    , next
+    , uncons
+    , split
+    , break
+    , span
+    
+    -- * Folds
+    -- $folds
+    , fold
+    , fold'
+    , foldM
+    , foldM'
+    , sum
+    , sum'
+    , product
+    , product'
+    , toList
+    , toListM
+    , toListM'
+    , foldrM
+    , foldrT
+    
+    -- * Short circuiting folds
+    -- , all
+    -- , any
+    -- , and
+    -- , or
+    -- , elem
+    -- , notElem
+    -- , find
+    -- , findIndex
+    -- , head
+    -- , index
+    -- , last
+    -- , length
+    -- , maximum
+    -- , minimum
+    -- , null
+
+    -- * Zips
+    , zip
+    , zipWith
+
+  ) where
+import Streaming.Internal
+
+import Control.Monad hiding (filterM, mapM, mapM_, foldM, replicateM, sequence)
+import Data.Data ( Data, Typeable )
+import Data.Functor.Identity
+import Control.Monad.Trans
+import qualified Prelude as Prelude                      
+import qualified Data.Foldable as Foldable
+import Text.Read (readMaybe)
+import Prelude hiding (map, mapM, mapM_, filter, drop, dropWhile, take, sum, product
+                      , iterate, repeat, replicate, splitAt
+                      , takeWhile, enumFrom, enumFromTo
+                      , print, zipWith, zip, seq, show, read
+                      , readLn, sequence, concat, span, break)
+
+import qualified GHC.IO.Exception as G
+import qualified System.IO as IO
+import Foreign.C.Error (Errno(Errno), ePIPE)
+import Control.Exception (throwIO, try)
+
+
+-- | A left-strict pair; the base functor for streams of individual elements.
+data Of a b = !a :> b
+    deriving (Data, Eq, Foldable, Functor, Ord,
+              Read, Show, Traversable, Typeable)
+infixr 4 :>
+
+lazily :: Of a b -> (a,b)
+lazily = \(a:>b) -> (a,b)
+{-# INLINE lazily #-}
+
+strictly :: (a,b) -> Of a b
+strictly = \(a,b) -> a :> b
+{-# INLINE strictly #-}
+
+break :: Monad m => (a -> Bool) -> Stream (Of a) m r 
+      -> Stream (Of a) m (Stream (Of a) m r)
+break pred = loop where
+  loop str = case str of 
+    Return r         -> Return (Return r)
+    Delay m          -> Delay $ liftM loop m
+    Step (a :> rest) -> if (pred a) 
+      then Return (Step (a :> rest))
+      else Step (a :> loop rest)
+{-# INLINEABLE break #-}
+
+{-| Apply an action to all values flowing downstream
+
+> let debug str = chain print str
+-}
+chain :: Monad m => (a -> m ()) -> Stream (Of a) m r -> Stream (Of a) m r
+chain f str = for str $ \a -> do
+    lift (f a)
+    yield a
+{-# INLINE chain #-}
+
+
+
+concat :: (Monad m, Foldable f) => Stream (Of (f a)) m r -> Stream (Of a) m r
+concat str = for str each
+{-# INLINE concat #-}
+
+-- ---------------
+-- drain
+-- ---------------
+
+-- | Reduce a stream, performing its actions but ignoring its elements.
+drain :: Monad m => Stream (Of a) m r -> m r
+drain = loop where
+  loop stream = case stream of 
+    Return r         -> return r
+    Delay m          -> m >>= loop 
+    Step (_ :> rest) -> loop rest
+
+-- ---------------
+-- drop
+-- ---------------
+
+-- | Ignore the first n elements of a stream, but carry out the actions
+drop :: (Monad m) => Int -> Stream (Of a) m r -> Stream (Of a) m r
+drop = loop where
+  loop n stream 
+    | n <= 0    = stream
+    | otherwise = case stream of
+      Return r       -> Return r
+      Delay ma       -> Delay (liftM (loop n) ma)
+      Step (a :> as) -> loop (n-1) as
+{-# INLINEABLE drop #-}
+
+-- ---------------
+-- dropWhile
+-- ---------------
+
+-- | Ignore elements of a stream until a test succeeds.
+dropWhile :: Monad m => (a -> Bool) -> Stream (Of a) m r -> Stream (Of a) m r
+dropWhile pred = loop where 
+  loop stream = case stream of
+    Return r       -> Return r
+    Delay ma       -> Delay (liftM loop ma)
+    Step (a :> as) -> if pred a 
+      then loop as
+      else Step (a :> as)
+{-# INLINEABLE dropWhile #-}
+
+-- ---------------
+-- each 
+-- ---------------
+
+-- | Stream the elements of a foldable container.
+each :: (Monad m, Foldable.Foldable f) => f a -> Stream (Of a) m ()
+each = Foldable.foldr (\a p -> Step (a :> p)) (Return ())
+{-# INLINE each #-}
+
+-- -----
+-- enumFrom
+-- ------
+
+enumFrom :: (Monad m, Num n) => n -> Stream (Of n) m ()
+enumFrom = loop where
+  loop !n = Step (n :> loop (n+1))
+{-# INLINEABLE enumFrom #-}
+
+enumFromTo :: (Monad m, Num n, Ord n) => n -> n -> Stream (Of n) m ()
+enumFromTo = loop where
+  loop !n m = if n <= m 
+    then Step (n :> loop (n+1) m)
+    else Return ()
+{-# INLINEABLE enumFromTo #-}
+
+enumFromStepN :: (Monad m, Num a) => a -> a -> Int -> Stream (Of a) m ()
+enumFromStepN start step = loop start where
+    loop !s m = case m of 
+      0 -> Return ()
+      _ -> Step (s :> loop (s+step) (m-1))
+{-# INLINEABLE enumFromStepN #-}
+
+-- ---------------
+-- filter 
+-- ---------------
+
+-- | Skip elements of a stream that fail a predicate
+filter  :: (Monad m) => (a -> Bool) -> Stream (Of a) m r -> Stream (Of a) m r
+filter pred = loop where
+  loop !str = case str of
+    Return r       -> Return r
+    Delay m        -> Delay (liftM loop m)
+    Step (a :> as) -> if pred a 
+                         then Step (a :> loop as)
+                         else loop as
+{-# INLINEABLE filter #-}
+
+-- ---------------
+-- filterM
+-- ---------------
+
+-- | Skip elements of a stream that fail a monadic test
+filterM  :: (Monad m) => (a -> m Bool) -> Stream (Of a) m r -> Stream (Of a) m r
+filterM pred = loop where
+  loop str = case str of
+    Return r       -> Return r
+    Delay m        -> Delay $ liftM loop m
+    Step (a :> as) -> Delay $ do 
+      bool <- pred a
+      if bool 
+        then return $ Step (a :> loop as)
+        else return $ loop as
+{-# INLINEABLE filterM #-}
+-- ---------------
+-- fold
+-- ---------------
+
+{- $folds
+    Use these to fold the elements of a 'Stream'.  The general folds 'fold', fold\'',
+    'foldM' and 'foldM\'' are arranged for use with 'Control.Foldl' All functions marked
+    with a final '\'' (e.g. 'fold\'', 'sum\') carry the stream's return value -- or, in
+    the case of 'maps\'' are tailored to take such an operation as argument.
+
+>  maps' sum' :: (Monad m, Num n) => Stream (Stream (Of n)) m r -> Stream (Of n) m r
+>  maps' (fold' mappend mempty id) :: :: (Monad m, Num n) => Stream (Stream (Of n)) m r -> Stream (Of n) m r
+-}
+
+{-| Strict fold of a 'Stream' of elements
+
+> Control.Foldl.purely fold :: Monad m => Fold a b -> Stream (Of a) m () -> m b
+-}
+fold :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m () -> m b
+fold step begin done stream0 = loop stream0 begin
+  where
+    loop stream !x = case stream of 
+      Return r         -> return (done x)
+      Delay m          -> m >>= \s -> loop s x
+      Step (a :> rest) -> loop rest (step x a)
+{-# INLINABLE fold #-}
+
+{-| Strict fold of a 'Stream' of elements that preserves the return value
+
+> Control.Foldl.purely fold' :: Monad m => Fold a b -> Stream (Of a) m r -> m (b, r)
+-}
+
+fold' :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> m (b, r)
+fold' step begin done s0 = loop s0 begin
+  where
+    loop stream !x = case stream of 
+      Return r         -> return (done x, r)
+      Delay m          -> m >>= \s -> loop s x
+      Step (a :> rest) -> loop rest (step x a)
+{-# INLINABLE fold' #-}
+
+{-| Strict, monadic fold of the elements of a 'Stream (Of a)'
+
+> Control.Foldl.impurely foldM :: Monad m => FoldM a b -> Stream (Of a) m () -> m b
+-}
+foldM
+    :: Monad m
+    => (x -> a -> m x) -> m x -> (x -> m b) -> Stream (Of a) m () -> m b
+foldM step begin done s0 = do
+    x0 <- begin
+    loop s0 x0
+  where
+    loop stream !x = case stream of 
+      Return r         -> done x 
+      Delay m          -> m >>= \s -> loop s x
+      Step (a :> rest) -> do
+        x' <- step x a
+        loop rest x'
+{-# INLINABLE foldM #-}
+
+{-| Strict, monadic fold of the elements of a 'Stream (Of a)'
+
+> Control.Foldl.impurely foldM' :: Monad m => FoldM a b -> Stream (Of a) m r -> m (b, r)
+-}
+foldM'
+    :: Monad m
+    => (x -> a -> m x) -> m x -> (x -> m b) -> Stream (Of a) m r -> m (b, r)
+foldM' step begin done str = do
+    x0 <- begin
+    loop str x0
+  where
+    loop stream !x = case stream of 
+      Return r         -> done x >>= \b -> return (b, r)
+      Delay m          -> m >>= \s -> loop s x
+      Step (a :> rest) -> do
+        x' <- step x a
+        loop rest x'
+{-# INLINABLE foldM' #-}
+
+{-| A natural right fold for consuming a stream of elements. 
+    See also the more general 'iterTM' in the 'Streaming' module 
+    and the still more general 'destroy'
+
+foldrT (\a p -> Pipes.yield a >> p) :: Monad m => Stream (Of a) m r -> Producer a m r
+foldrT (\a p -> Conduit.yield a >> p) :: Monad m => Stream (Of a) m r -> Conduit a m r
+
+-}
+
+foldrT :: (Monad m, MonadTrans t, Monad (t m)) 
+       => (a -> t m r -> t m r) -> Stream (Of a) m r -> t m r
+foldrT step = loop where
+  loop stream = case stream of
+    Return r       -> return r
+    Delay m        -> lift m >>= loop
+    Step (a :> as) -> step a (loop as)
+{-# INLINABLE foldrT #-}  
+
+{-| A natural right fold for consuming a stream of elements.
+    See also the more general 'iterT' in the 'Streaming' module and the
+    still more general 'destroy'
+-}
+foldrM :: Monad m 
+       => (a -> m r -> m r) -> Stream (Of a) m r -> m r
+foldrM step = loop where
+  loop stream = case stream of
+    Return r       -> return r
+    Delay m        -> m >>= loop
+    Step (a :> as) -> step a (loop as)
+{-# INLINABLE foldrM #-}  
+
+-- ---------------
+-- for
+-- ---------------
+
+-- | @for@ replaces each element of a stream with an associated stream. Note that the
+-- associated stream may layer any functor. 
+for :: (Monad m, Functor f) => Stream (Of a) m r -> (a -> Stream f m x) -> Stream f m r
+for str0 act = loop str0 where
+  loop str = case str of
+    Return r         -> Return r 
+    Delay m          -> Delay $ liftM loop m
+    Step (a :> rest) -> do
+      act a
+      loop rest
+{-# INLINEABLE for #-}
+
+-- ---------------
+-- iterate
+-- ---------------
+
+-- | Iterate a pure function from a seed value, streaming the results forever
+iterate :: (a -> a) -> a -> Stream (Of a) m r
+iterate f = loop where
+  loop a' = Step (a' :> loop (f a'))
+{-# INLINEABLE iterate #-}
+
+-- | Iterate a monadic function from a seed value, streaming the results forever
+iterateM :: Monad m => (a -> m a) -> m a -> Stream (Of a) m r
+iterateM f = loop where
+  loop ma  = Delay $ do 
+    a <- ma
+    return (Step (a :> loop (f a)))
+{-# INLINEABLE iterateM #-}
+
+-- ---------------
+-- map
+-- ---------------
+
+-- | Standard map on the elements of a stream.
+map :: Monad m => (a -> b) -> Stream (Of a) m r -> Stream (Of b) m r
+map f = loop where
+  loop stream = case stream of
+    Return r -> Return r
+    Delay m -> Delay (liftM loop m)
+    Step (a :> as) -> Step (f a :> loop as)
+{-# INLINEABLE map #-}
+
+-- ---------------
+-- mapFoldable
+-- ---------------
+
+{-| For each element of a stream, stream a foldable container of elements instead
+
+>>> D.print $ D.mapFoldable show $ D.yield 12
+'1'
+'2'
+
+-}
+mapFoldable :: (Monad m, Foldable t) => (a -> t b) -> Stream (Of a) m r -> Stream (Of b) m r
+mapFoldable f str = for str (\a -> each (f a)) -- as in pipes
+
+-- | Replace each element of a stream with the result of a monadic action
+mapM :: Monad m => (a -> m b) -> Stream (Of a) m r -> Stream (Of b) m r
+mapM f = loop where
+  loop str = case str of 
+    Return r       -> Return r 
+    Delay m        -> Delay $ liftM loop m
+    Step (a :> as) -> Delay $ do 
+      a' <- f a 
+      return $ Step (a' :> loop as) 
+{-# INLINEABLE mapM #-}
+
+
+{-| Reduce a stream to its return value with a monadic action.
+
+>>>  mapM_ Prelude.print $ each [1..3] >> return True
+1
+2
+3
+True
+
+-}
+mapM_ :: Monad m => (a -> m b) -> Stream (Of a) m r -> m r
+mapM_ f = loop where
+  loop str = case str of 
+    Return r       -> return r 
+    Delay m        -> m >>= loop
+    Step (a :> as) -> do 
+      f a 
+      loop as 
+{-# INLINEABLE mapM_ #-}
+{-| Map free layers of a functor to a corresponding stream of individual elements. This
+     simplifies the use of folds marked with a \'\'\' in @Streaming.Prelude@
+
+> maps' sum' :: (Monad m, Num a) => Stream (Stream (Of a) m) m r -> Stream (Of a) m r
+> maps' (Pipes.fold' (+) (0::Int) id) :: Monad m => Stream (Producer Int m) m r -> Stream (Of Int) m r
+
+-}
+maps' :: (Monad m, Functor f) 
+          => (forall x . f x -> m (a, x)) 
+          -> Stream f m r 
+          -> Stream (Of a) m r
+maps' phi = loop where
+  loop stream = case stream of 
+    Return r -> Return r
+    Delay m -> Delay $ liftM loop m
+    Step fs -> Delay $ liftM (Step . uncurry (:>)) (phi (fmap loop fs))
+{-# INLINABLE maps' #-}
+
+{-| The standard way of inspecting the first item in a stream of elements, if the
+     stream is still \'running\'. The @Right@ case contains a 
+     Haskell pair, where the more general @inspect@ would return a left-strict pair. 
+     There is no reason to prefer @inspect@ since, if the @Right@ case is exposed, 
+     the first element in the pair will have been evaluated to whnf.
+
+next :: Monad m => Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))
+inspect :: Monad m => Stream (Of a) m r -> m (Either r (Of a (Stream (Of a) m r)))
+
+IOStreams.unfoldM (liftM (either (const Nothing) Just) . next) :: Stream (Of a) IO b -> IO (InputStream a)
+Conduit.unfoldM (liftM (either (const Nothing) Just) . next) :: Stream (Of a) m r -> Source a m r
+
+-}
+next :: Monad m => Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))
+next = loop where
+  loop stream = case stream of
+    Return r         -> return (Left r)
+    Delay m          -> m >>= loop
+    Step (a :> rest) -> return (Right (a,rest))
+{-# INLINABLE next #-}
+
+
+{-| Inspect the first item in a stream of elements, without a return value. 
+    Useful for unfolding into another streaming type.
+
+IOStreams.unfoldM uncons :: Stream (Of a) IO b -> IO (InputStream a)
+Conduit.unfoldM uncons :: Stream (Of o) m r -> Conduit.Source m o
+
+-}
+uncons :: Monad m => Stream (Of a) m () -> m (Maybe (a, Stream (Of a) m ()))
+uncons = loop where
+  loop stream = case stream of
+    Return ()        -> return Nothing
+    Delay m          -> m >>= loop
+    Step (a :> rest) -> return (Just (a,rest))
+{-# INLINABLE uncons #-}
+
+
+-- | Fold a 'Stream' of numbers into their product
+product :: (Monad m, Num a) => Stream (Of a) m () -> m a
+product = fold (*) 1 id
+{-# INLINE product #-}
+
+{-| Fold a 'Stream' of numbers into their product with the return value
+
+>  mapsFold product' :: Stream (Stream (Of Int)) m r -> Stream (Of Int) m r
+-}
+product' :: (Monad m, Num a) => Stream (Of a) m r -> m (a,r)
+product' = fold' (*) 1 id
+{-# INLINAE product' #-}
+
+-- ---------------
+-- read
+-- ---------------
+
+-- | Make a stream of strings into a stream of parsed values, skipping bad cases
+read :: (Monad m, Read a) => Stream (Of String) m r -> Stream (Of a) m r
+read stream = for stream $ \str -> case readMaybe str of 
+  Nothing -> return ()
+  Just r  -> yield r
+{-# INLINE read #-}
+
+-- ---------------
+-- repeat
+-- ---------------
+
+repeat :: a -> Stream (Of a) m r
+repeat a = loop where loop = Step (a :> loop)
+{-# INLINE repeat #-}
+
+repeatM :: Monad m => m a -> Stream (Of a) m r
+repeatM ma = loop where
+  loop = Delay $ do 
+    a <- ma 
+    return (Step (a :> loop))
+{-# INLINEABLE repeatM #-}
+
+-- ---------------
+-- replicate 
+-- ---------------
+
+replicate :: Monad m => Int -> a -> Stream (Of a) m ()
+replicate n a = loop n where
+  loop 0 = Return ()
+  loop m = Step (a :> loop (m-1))
+{-# INLINEABLE replicate #-}
+
+-- | Repeat an action, streaming the results.
+replicateM :: Monad m => Int -> m a -> Stream (Of a) m ()
+replicateM n ma = loop n where 
+  loop 0 = Return ()
+  loop n = Delay $ do 
+    a <- ma 
+    return (Step $ a :> loop (n-1))
+{-# INLINEABLE replicateM #-}
+
+
+{-| Strict left scan, streaming, e.g. successive partial results.
+
+> Control.Foldl.purely scan :: Monad m => Fold a b -> Stream (Of a) m r -> Stream (Of b) m r
+-}
+scan :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> Stream (Of b) m r
+scan step begin done = loop begin
+  where
+    loop !x stream = do 
+      yield (done x)
+      case stream of 
+        Return r -> Return r
+        Delay m  -> Delay $ liftM (loop x) m
+        Step (a :> rest) -> do
+          let x' = step x a
+          loop x' rest
+{-# INLINABLE scan #-}
+
+{-| Strict, monadic left scan
+
+> Control.Foldl.impurely scanM :: Monad m => FoldM a m b -> Stream (Of a) m r -> Stream (Of b) m r
+-}
+scanM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> Stream (Of a) m r -> Stream (Of b) m r
+scanM step begin done str = do
+    x <- lift begin
+    loop x str
+  where
+    loop !x stream = do 
+      b <- lift (done x)
+      yield b
+      case stream of 
+        Return r -> Return r
+        Delay m  -> Delay $ liftM (loop x) m
+        Step (a :> rest) -> do
+          x' <- lift $ step x a
+          loop x' rest
+{-# INLINABLE scanM #-}
+
+-- ---------------
+-- sequence
+-- ---------------
+
+-- | Like the 'Data.List.sequence' but streaming. The result type is a
+-- stream of a\'s, but is not accumulated; the effects of the elements
+-- of the original stream are interleaved in the resulting stream.
+
+sequence :: Monad m => Stream (Of (m a)) m r -> Stream (Of a) m r
+sequence = loop where
+  loop stream = case stream of
+    Return r          -> Return r
+    Delay m           -> Delay $ liftM loop m
+    Step (ma :> rest) -> Delay $ do
+      a <- ma
+      return (Step (a :> loop rest))
+{-# INLINEABLE sequence #-}
+
+-- ---------------
+-- show
+-- ---------------
+
+show :: (Monad m, Show a) => Stream (Of a) m r -> Stream (Of String) m r
+show = map Prelude.show
+{-# INLINE show #-}
+-- ---------------
+-- sum 
+-- ---------------
+
+-- | Fold a 'Stream' of numbers into their sum
+sum :: (Monad m, Num a) => Stream (Of a) m () -> m a
+sum = fold (+) 0 id
+{-# INLINE sum #-}
+
+{-| Fold a 'Stream' of numbers into their sum with the return value
+
+>  mapsFold sum' :: Stream (Stream (Of Int)) m r -> Stream (Of Int) m r
+-}
+sum' :: (Monad m, Num a) => Stream (Of a) m r -> m (a, r)
+sum' = fold' (+) 0 id
+{-# INLINE sum' #-}
+
+-- ---------------
+-- span
+-- ---------------
+
+-- | Stream elements until one fails the condition, return the rest.
+span :: Monad m => (a -> Bool) -> Stream (Of a) m r 
+      -> Stream (Of a) m (Stream (Of a) m r)
+span pred = loop where
+  loop str = case str of 
+    Return r         -> Return (Return r)
+    Delay m          -> Delay $ liftM loop m
+    Step (a :> rest) -> if pred a 
+      then Step (a :> loop rest)
+      else Return (Step (a :> rest))
+{-# INLINEABLE span #-}
+
+
+-- ---------------
+-- take
+-- ---------------
+
+-- | End stream after n elements; the original return value is lost.
+-- 'splitAt' preserves this information. Note the function is functor-general.
+
+take :: (Monad m, Functor f) => Int -> Stream f m r -> Stream f m ()
+take = loop where
+  loop n p = when (n > 0) $
+    case p of Step fas -> Step (fmap (loop (n-1)) fas)
+              Delay m -> Delay (liftM (loop n) m)
+              Return r -> Return ()
+{-# INLINEABLE take #-}
+
+-- ---------------
+-- takeWhile
+-- ---------------
+
+-- | End stream when an element fails a condition; the original return value is lost
+-- 'span' preserves this information.
+takeWhile :: Monad m => (a -> Bool) -> Stream (Of a) m r -> Stream (Of a) m ()
+takeWhile pred = loop where
+  loop str = case str of 
+    Step (a :> as) -> when (pred a) (Step (a :> loop as))
+    Delay m              -> Delay (liftM loop m)
+    Return r              -> Return ()
+{-# INLINEABLE takeWhile #-}
+
+
+
+-- | Convert a pure 'Stream (Of a) into a list of a
+toList :: Stream (Of a) Identity () -> [a]
+toList = loop
+  where
+    loop stream = case stream of
+       Return _                 -> []
+       Delay (Identity stream') -> loop stream'
+       Step (a :> rest)         -> a : loop rest
+{-# INLINABLE toList #-}
+
+{-| Convert an effectful 'Stream (Of a)' into a list of a
+
+    Note: 'toListM' is not an idiomatic use of @pipes@, but I provide it for
+    simple testing purposes.  Idiomatic @pipes@ style consumes the elements
+    immediately as they are generated instead of loading all elements into
+    memory.
+-}
+toListM :: Monad m => Stream (Of a) m () -> m [a]
+toListM = fold (\diff a ls -> diff (a: ls)) id (\diff -> diff [])
+{-# INLINE toListM #-}
+
+
+{-| Convert an effectful 'Stream' into a list alongside the return value
+
+    Note: 'toListM'' is not an idiomatic use of @streaming@, but I provide it for
+    simple testing purposes.  Idiomatic @streaming@ style, like idiomatic @pipes@ style
+    consumes the elements as they are generated instead of loading all elements into
+    memory.
+
+>  mapsFold toListM' :: Stream (Stream (Of a)) m r -> Stream (Of [a]) m 
+-}
+toListM' :: Monad m => Stream (Of a) m r -> m ([a], r)
+toListM' = fold' (\diff a ls -> diff (a: ls)) id (\diff -> diff [])
+{-# INLINE toListM' #-}
+
+{-| Build a @Stream@ by unfolding steps starting from a seed. 
+    This is one natural way to consume a 'Pipes.Producer'. The 
+    more general 'unfold' would require dealing with the left-strict pair
+    we are using.
+
+unfoldr Pipes.next :: Monad m => Producer a m r -> Stream (Of a) m r
+unfold (curry (:>) . Pipes.next) :: Monad m => Producer a m r -> Stream (Of a) m r
+
+-}
+unfoldr :: Monad m 
+        => (s -> m (Either r (a, s))) -> s -> Stream (Of a) m r
+unfoldr step = loop where
+  loop s0 = Delay $ do 
+    e <- step s0
+    case e of
+      Left r -> return (Return r)
+      Right (a,s) -> return (Step (a :> loop s))
+{-# INLINABLE unfoldr #-}
+
+-- ---------------------------------------
+-- yield
+-- ---------------------------------------
+
+-- | A singleton stream
+yield :: Monad m => a -> Stream (Of a) m ()
+yield a = Step (a :> Return ())
+{-# INLINE yield #-}
+
+-- | Zip two 'Streams's 
+zip :: Monad m
+    => (Stream (Of a) m r)
+    -> (Stream (Of b) m r)
+    -> (Stream (Of (a,b)) m r)
+zip = zipWith (,)
+{-# INLINE zip #-}
+
+-- | Zip two 'Streams's using the provided combining function
+zipWith :: Monad m
+    => (a -> b -> c)
+    -> (Stream (Of a) m r)
+    -> (Stream (Of b) m r)
+    -> (Stream (Of c) m r)
+zipWith f = loop
+  where
+    loop str0 str1 = case str0 of
+      Return r          -> Return r
+      Delay m           -> Delay $ liftM (\str -> loop str str1) m 
+      Step (a :> rest0) -> case str1 of
+        Return r          -> Return r
+        Delay m           -> Delay $ liftM (loop str0) m
+        Step (b :> rest1) -> Step (f a b :>loop rest0 rest1)
+{-# INLINABLE zipWith #-}
+
+-- --------------
+-- IO fripperies 
+-- --------------
+
+-- | repeatedly stream lines as 'String' from stdin
+stdinLn :: MonadIO m => Stream (Of String) m ()
+stdinLn = fromHandle IO.stdin
+{-# INLINABLE stdinLn #-}
+
+-- | 'read' values from 'IO.stdin', ignoring failed parses
+readLn :: (MonadIO m, Read a) => Stream (Of a) m ()
+readLn = for stdinLn $ \str -> case readMaybe str of 
+  Nothing -> return ()
+  Just n  -> yield n
+{-# INLINABLE readLn #-}
+
+{-| Read 'String's from a 'IO.Handle' using 'IO.hGetLine'
+
+    Terminates on end of input
+-}
+fromHandle :: MonadIO m => IO.Handle -> Stream (Of String) m ()
+fromHandle h = go
+  where
+    go = do
+        eof <- liftIO $ IO.hIsEOF h
+        unless eof $ do
+            str <- liftIO $ IO.hGetLine h
+            yield str
+            go
+{-# INLINABLE fromHandle #-}     
+
+toHandle :: MonadIO m => IO.Handle -> Stream (Of String) m r -> m r
+toHandle handle = loop where
+  loop str = case str of
+    Return r         -> return r
+    Delay m          -> m >>= loop 
+    Step (s :> rest) -> do 
+      liftIO $ IO.hPutStrLn handle s
+      loop rest
+{-# INLINABLE toHandle #-} 
+
+print :: (MonadIO m, Show a) => Stream (Of a) m r -> m r
+print = loop where
+  loop stream = case stream of 
+    Return r         -> return r 
+    Delay m          -> m >>= loop
+    Step (a :> rest) -> do 
+      liftIO (Prelude.print a)
+      loop rest
+
+-- | Evaluate all values flowing downstream to WHNF
+seq :: Monad m => Stream (Of a) m r -> Stream (Of a) m r 
+seq str = for str $ \a -> yield $! a
+{-# INLINABLE seq #-}
+
+{-| Write 'String's to 'IO.stdout' using 'putStrLn'
+
+    Unlike 'toHandle', 'stdoutLn' gracefully terminates on a broken output pipe
+-}
+stdoutLn :: MonadIO m => Stream (Of String) m () -> m ()
+stdoutLn = loop
+  where
+    loop stream = case stream of 
+      Return _         -> return () 
+      Delay m          -> m >>= loop
+      Step (s :> rest) -> do
+        x   <- liftIO $ try (putStrLn s)
+        case x of
+           Left (G.IOError { G.ioe_type  = G.ResourceVanished
+                           , G.ioe_errno = Just ioe })
+                | Errno ioe == ePIPE
+                    -> return ()
+           Left  e  -> liftIO (throwIO e)
+           Right () -> loop rest
+{-# INLINABLE stdoutLn #-}
+
+
+{-| Write 'String's to 'IO.stdout' using 'putStrLn'
+
+    This does not handle a broken output pipe, but has a polymorphic return
+    value
+-}
+
+stdoutLn' :: MonadIO m => Stream (Of String) m r -> m r
+stdoutLn' = loop where 
+  loop stream = case stream of 
+    Return r         -> return r 
+    Delay m          -> m >>= loop
+    Step (s :> rest) -> liftIO (putStrLn s) >> loop rest
+{-# INLINE stdoutLn' #-}
+
+
+-- -- * Producers
+-- -- $producers
+--   stdinLn  -- 
+-- , readLn -- 
+-- , fromHandle -- 
+-- , repeatM -- 
+-- , replicateM --
+--
+-- -- * Consumers
+-- -- $consumers
+-- , stdoutLn --
+-- , stdoutLn' --
+-- , mapM_ --
+-- , print -- 
+-- , toHandle --
+-- , drain --
+--
+-- -- * Pipes
+-- -- $pipes
+-- , map -- 
+-- , mapM --
+-- , sequence -- 
+-- , mapFoldable -- 
+-- , filter --
+-- , filterM --
+-- , take --
+-- , takeWhile --
+-- , takeWhile' --
+-- , drop --
+-- , dropWhile -- 
+-- , concat --
+-- , elemIndices
+-- , findIndices
+-- , scan --
+-- , scanM --
+-- , chain --
+-- , read --
+-- , show -- 
+-- , seq --
+--
+-- -- * Folds
+-- -- $folds
+-- , fold --
+-- , fold' --
+-- , foldM --
+-- , foldM' --
+-- , all
+-- , any
+-- , and
+-- , or
+-- , elem
+-- , notElem
+-- , find
+-- , findIndex
+-- , head
+-- , index
+-- , last
+-- , length
+-- , maximum
+-- , minimum
+-- , null
+-- , sum --
+-- , product --
+-- , toList --
+-- , toListM --
+-- , toListM' --
+--
+-- -- * Zips
+-- , zip --
+-- , zipWith --
+--
diff --git a/streaming.cabal b/streaming.cabal
new file mode 100644
--- /dev/null
+++ b/streaming.cabal
@@ -0,0 +1,45 @@
+name:                streaming
+version:             0.1.0.0
+cabal-version:       >=1.10
+build-type:          Simple
+synopsis:            A general free monad transformer optimized for streaming applications.
+description:         Stream is an optimized variant of FreeT.
+                     It can be used wherever FreeT is used, but is focused
+                     on employment with functors like '((,) a)' which generate
+                     effectful sequences or \"producers\"
+license:             BSD3
+license-file:        LICENSE
+author:              michaelt
+maintainer:          what_is_it_to_do_anything@yahoo.com
+stability:           Experimental
+homepage:            https://github.com/michaelt/streaming
+bug-reports:         https://github.com/michaelt/streaming/issues
+category:            Data, Pipes
+source-repository head
+    type: git
+    location: https://github.com/michaelt/streaming
+
+
+library
+  exposed-modules:     Streaming, 
+                       Streaming.Prelude,
+                       Streaming.Internal
+
+    -- other-modules:       
+  other-extensions:    LambdaCase, RankNTypes, EmptyCase, 
+                       StandaloneDeriving, FlexibleContexts, 
+                       DeriveDataTypeable, DeriveFoldable, 
+                       DeriveFunctor, DeriveTraversable, 
+                       UndecidableInstances
+  
+  build-depends:       base >=4.7 && <4.9
+                     , mtl >=2.1 && <2.3
+                     , mmorph >=1.0 && <1.2
+                     , transformers >=0.3 && <0.5
+                     , ghc-prim
+
+  default-language:  Haskell2010
+  ghc-options:      -O2   
+  
+
+
