diff --git a/library/Potoki/Core/Consume.hs b/library/Potoki/Core/Consume.hs
--- a/library/Potoki/Core/Consume.hs
+++ b/library/Potoki/Core/Consume.hs
@@ -1,64 +1,98 @@
-module Potoki.Core.Consume where
+module Potoki.Core.Consume
+(
+  Consume(..),
+  apConcurrently,
+  list,
+  sum,
+  transform,
+  count,
+  head,
+  last,
+  reverseList,
+  vector,
+  concat,
+  fold,
+  foldInIO,
+  folding,
+  foldingInIO,
+  execState,
+  writeBytesToFile,
+  appendBytesToFile,
+  deleteFiles,
+  printBytes,
+  printText,
+  printString,
+  parseBytes,
+  parseText,
+  concurrently,
+)
+where
 
-import Potoki.Core.Prelude
+import Potoki.Core.Prelude hiding (sum, head, fold, concat, last)
+import Potoki.Core.Types
 import qualified Potoki.Core.Fetch as A
-import qualified Potoki.Core.Transform.Types as B
+import qualified Acquire.IO as B
+import qualified Potoki.Core.Transform as J
+import qualified Potoki.Core.IO.Fetch as L
+import qualified Data.ByteString as C
+import qualified Data.Attoparsec.ByteString as E
+import qualified Data.Attoparsec.Text as F
+import qualified Data.Attoparsec.Types as I
+import qualified Data.Text.IO as K
+import qualified Control.Foldl as D
+import qualified System.Directory as G
+import qualified Potoki.Core.Transform.Concurrency as B
+import qualified Control.Monad.Trans.State.Strict as O
 
 
-{-|
-Active consumer of input into output.
-Sort of like a reducer in Map/Reduce.
-
-Automates the management of resources.
--}
-newtype Consume input output =
-  {-|
-  An action, which executes the provided fetch in IO,
-  while managing the resources behind the scenes.
-  -}
-  Consume (A.Fetch input -> IO output)
-
 instance Profunctor Consume where
   {-# INLINE dimap #-}
   dimap inputMapping outputMapping (Consume consume) =
-    Consume (\ fetch -> fmap outputMapping (consume (fmap inputMapping fetch)))
+    Consume (\ fetch -> fmap outputMapping (consume $ fmap inputMapping fetch))
 
 instance Choice Consume where
+  right' :: Consume a b -> Consume (Either c a) (Either c b)
   right' (Consume rightConsumeIO) =
-    Consume $ \ (A.Fetch eitherFetchIO) -> do
-      fetchedLeftMaybeRef <- newIORef Nothing
-      consumedRight <- 
-        rightConsumeIO $ A.Fetch $ \ nil just -> join $ eitherFetchIO (return nil) $ \ case
-          Right !fetchedRight -> return (just fetchedRight)
-          Left !fetchedLeft -> writeIORef fetchedLeftMaybeRef (Just fetchedLeft) >> return nil
-      fetchedLeftMaybe <- readIORef fetchedLeftMaybeRef
-      case fetchedLeftMaybe of
-        Nothing -> return (Right consumedRight)
-        Just fetchedLeft -> return (Left fetchedLeft)
+     Consume $ \ (Fetch eitherFetchIO) -> do
+       fetchedLeftMaybeRef <- newIORef Nothing
+       consumedRight <-
+         rightConsumeIO $ Fetch $ do
+           eitherFetch <- eitherFetchIO
+           case eitherFetch of
+             Nothing      -> return Nothing
+             Just element -> case element of
+               Right fetchedRight -> return $ Just fetchedRight
+               Left  fetchedLeft  -> do
+                 writeIORef fetchedLeftMaybeRef $ Just fetchedLeft
+                 return Nothing
+       fetchedLeftMaybe <- readIORef fetchedLeftMaybeRef
+       case fetchedLeftMaybe of
+         Nothing          -> return $ Right consumedRight
+         Just fetchedLeft -> return $ Left fetchedLeft 
 
 instance Functor (Consume input) where
   fmap = rmap
 
 instance Applicative (Consume a) where
-  pure x = Consume $ \_ -> pure x
+  pure x = Consume $ \ _ -> pure x
 
   Consume leftConsumeIO <*> Consume rightConsumeIO =
-    Consume $ \fetch -> leftConsumeIO fetch <*> rightConsumeIO fetch
+    Consume $ \ fetch -> leftConsumeIO fetch <*> rightConsumeIO fetch
 
 instance Monad (Consume a) where
-  Consume leftConsumeIO >>= toRightConsumeIO = Consume $ \fetch -> do
+  Consume leftConsumeIO >>= toRightConsumeIO = Consume $ \ fetch -> do
     Consume rightConsumeIO <- toRightConsumeIO <$> leftConsumeIO fetch
     rightConsumeIO fetch
 
 instance MonadIO (Consume a) where
-  liftIO a = Consume $ \_ -> a
+  liftIO a = Consume $ \ _ -> a
 
 apConcurrently :: Consume a (b -> c) -> Consume a b -> Consume a c
 apConcurrently (Consume leftConsumeIO) (Consume rightConsumeIO) =
   Consume $ \ fetch -> do
     (leftFetch, rightFetch) <- A.duplicate fetch
     rightOutputVar <- newEmptyMVar
-    forkIO $ do
+    _ <- forkIO $ do
       !rightOutput <- rightConsumeIO rightFetch
       putMVar rightOutputVar rightOutput
     !leftOutput <- leftConsumeIO leftFetch
@@ -68,28 +102,222 @@
 {-# INLINABLE list #-}
 list :: Consume input [input]
 list =
-  Consume $ \ (A.Fetch fetchIO) ->
-  let
-    build !acc =
-      join
-        (fetchIO
-          (pure (acc []))
-          (\ !element -> build (acc . (:) element)))
-    in build id
+  Consume $ \ (Fetch fetchIO) ->
+    let 
+      build !acc = do
+        fetch <- fetchIO
+        case fetch of
+          Nothing       -> pure $ acc []
+          Just !element -> build $ acc . (:) element
+     in build id
 
 {-# INLINE sum #-}
 sum :: Num num => Consume num num
 sum =
-  Consume $ \ (A.Fetch fetchIO) ->
-  let
-    build !acc =
-      join
-        (fetchIO
-          (pure acc)
-          (\ !element -> build (element + acc)))
-    in build 0
+  Consume $ \ (Fetch fetchIO) ->
+    let
+      build !acc = do
+        fetch <- fetchIO
+        case fetch of
+          Nothing       -> pure acc
+          Just !element -> build $ element + acc
+     in build 0
 
 {-# INLINABLE transform #-}
-transform :: B.Transform input output -> Consume output sinkOutput -> Consume input sinkOutput
-transform (B.Transform transform) (Consume sink) =
-  Consume (transform >=> sink)
+transform :: Transform input1 input2 -> Consume input2 output -> Consume input1 output
+transform (Transform transformAcquire) (Consume consumeIO) =
+  Consume $ \ fetch -> B.acquire (transformAcquire fetch) consumeIO
+
+{-# INLINABLE head #-}
+head :: Consume input (Maybe input)
+head =
+  Consume (\ (A.Fetch fetchIO) -> fetchIO)
+
+{-# INLINABLE last #-}
+last :: Consume input (Maybe input)
+last = 
+  fold D.last 
+
+{-|
+A faster alternative to "list",
+which however constructs the list in the reverse order.
+-}
+{-# INLINABLE reverseList #-}
+reverseList :: Consume input [input]
+reverseList =
+  Consume $ \ (A.Fetch fetchIO) -> build fetchIO []
+  where
+    build fetchIO !acc =
+      fetchIO >>= \case
+        Nothing -> pure acc
+        Just element -> build fetchIO (element : acc)
+
+{-# INLINABLE vector #-}
+vector :: Consume input (Vector input)
+vector =
+  foldInIO D.vectorM
+
+{-# INLINABLE count #-}
+count :: Consume input Int
+count =
+  Consume $ \ (A.Fetch fetchIO) -> build fetchIO 0
+  where
+    build fetchIO !acc =
+      fetchIO >>= \case
+        Nothing -> pure acc
+        Just _ -> build fetchIO (succ acc)
+
+{-# INLINABLE concat #-}
+concat :: Monoid monoid => Consume monoid monoid
+concat =
+  Consume $ \ (A.Fetch fetchIO) -> build fetchIO mempty
+  where
+    build fetchIO !acc =
+      fetchIO >>= \case
+        Nothing -> pure acc
+        Just element -> build fetchIO (acc <> element)
+
+{-# INLINABLE processInIO #-}
+processInIO :: IO () -> (element -> IO ()) -> Consume element ()
+processInIO stop process =
+  Consume (\ fetch -> L.fetchAndHandleAll fetch stop process)
+
+{-# INLINABLE printBytes #-}
+printBytes :: Consume ByteString ()
+printBytes =
+  processInIO (putChar '\n') C.putStr
+
+{-# INLINABLE printText #-}
+printText :: Consume Text ()
+printText =
+  processInIO (putChar '\n') K.putStr
+
+{-# INLINABLE printString #-}
+printString :: Consume String ()
+printString =
+  processInIO (putChar '\n') putStr
+
+{-|
+Overwrite a file.
+
+* Exception-free
+* Automatic resource management
+-}
+{-# INLINABLE writeBytesToFile #-}
+writeBytesToFile :: FilePath -> Consume ByteString (Either IOException ())
+writeBytesToFile path =
+  Consume $ \ fetch ->
+  try $ withFile path WriteMode $ \ handleVal ->
+  do
+    hSetBuffering handleVal NoBuffering
+    L.fetchAndHandleAll fetch (return ()) (C.hPut handleVal)
+
+{-|
+Append to a file.
+
+* Exception-free
+* Automatic resource management
+-}
+{-# INLINABLE appendBytesToFile #-}
+appendBytesToFile :: FilePath -> Consume ByteString (Either IOException ())
+appendBytesToFile path =
+  Consume $ \ fetch ->
+  try $ withFile path AppendMode $ \ handleVal ->
+  do
+    hSetBuffering handleVal NoBuffering
+    L.fetchAndHandleAll fetch (return ()) (C.hPut handleVal)
+
+{-# INLINABLE deleteFiles #-}
+deleteFiles :: Consume FilePath (Either IOException ())
+deleteFiles =
+  Consume $ \ fetch ->
+  try $ L.fetchAndHandleAll fetch (return ()) G.removeFile
+
+{-# INLINABLE fold #-}
+fold :: D.Fold input output -> Consume input output
+fold (D.Fold step initVal finish) =
+  Consume $ \ (A.Fetch fetch) -> build fetch initVal
+  where
+    build fetch !acc =
+      fetch >>= \case
+        Nothing -> pure $ finish acc
+        Just input -> build fetch (step acc input)
+
+{-# INLINABLE foldInIO #-}
+foldInIO :: D.FoldM IO input output -> Consume input output
+foldInIO (D.FoldM step initVal finish) =
+  Consume $ \ (A.Fetch fetch) -> build fetch =<< initVal
+  where
+    build fetch !acc =
+      fetch >>= \case
+        Nothing -> finish acc
+        Just input -> step acc input >>= build fetch
+
+{-# INLINABLE folding #-}
+folding :: D.Fold a b -> Consume a c -> Consume a (b, c)
+folding (D.Fold step initVal extract) (Consume consumeIO) =
+  Consume $ \ fetch -> do
+    foldStateRef <- newIORef initVal
+    consumptionResult <-
+      consumeIO (A.handlingElements (\ element -> do
+        !newState <- flip step element <$> readIORef foldStateRef
+        writeIORef foldStateRef newState) fetch)
+    foldResult <- extract <$> readIORef foldStateRef
+    return (foldResult, consumptionResult)
+
+{-# INLINABLE foldingInIO #-}
+foldingInIO :: D.FoldM IO a b -> Consume a c -> Consume a (b, c)
+foldingInIO (D.FoldM step initVal extract) (Consume consumeIO) =
+  Consume $ \ fetch -> do
+    foldStateRef <- newIORef =<< initVal
+    consumptionResult <-
+      consumeIO (A.handlingElements (\ element -> do
+        !newState <- flip step element =<< readIORef foldStateRef
+        writeIORef foldStateRef newState) fetch)
+    foldResult <- extract =<< readIORef foldStateRef
+    return (foldResult, consumptionResult)
+
+{-# INLINE execState #-}
+execState :: (a -> O.State s b) -> s -> Consume a s
+execState stateFn initialState = 
+  fold $ D.Fold (\currentState input -> snd $ O.runState (stateFn input) currentState) initialState id
+
+{-# INLINABLE runParseResult #-}
+runParseResult :: (Monoid input, Eq input) => (input -> I.IResult input output) -> Consume input (Either Text output)
+runParseResult inputToResult =
+  Consume $ \ (A.Fetch fetchInput) ->
+  let
+    just !input =
+      case inputToResult input of
+        I.Partial newInputToResult -> consume newInputToResult
+        I.Done _ parsed -> return (Right parsed)
+        I.Fail _ contexts message -> return (Left resultMessage)
+          where
+            resultMessage =
+              if null contexts
+                then fromString message
+                else fromString (showString (intercalate " > " contexts) (showString ": " message))
+    consume _ =
+      fetchInput >>= \case
+        Nothing -> just mempty
+        Just !input -> just input
+    in consume inputToResult
+
+{-# INLINABLE parseBytes #-}
+parseBytes :: E.Parser output -> Consume ByteString (Either Text output)
+parseBytes =
+  runParseResult . E.parse
+
+{-# INLINABLE parseText #-}
+parseText :: F.Parser output -> Consume Text (Either Text output)
+parseText =
+  runParseResult . F.parse
+
+{-|
+Execute a Consume concurrently and consume its results.
+-}
+{-# INLINABLE concurrently #-}
+concurrently :: Int -> Consume a b -> Consume b c -> Consume a c
+concurrently amount consume1 consume2 =
+  transform (B.concurrently amount (J.consume consume1)) consume2
+  
diff --git a/library/Potoki/Core/Fetch.hs b/library/Potoki/Core/Fetch.hs
--- a/library/Potoki/Core/Fetch.hs
+++ b/library/Potoki/Core/Fetch.hs
@@ -1,43 +1,61 @@
-module Potoki.Core.Fetch where
+module Potoki.Core.Fetch
+(
+  Fetch(..),
+  duplicate,
+  maybeRef,
+  list,
+  firstCachingSecond,
+  bothFetchingFirst,
+  rightHandlingLeft,
+  rightCachingLeft,
+  eitherFetchingRight,
+  signaling,
+  ioFetch,
+  handleBytes,
+  handleBytesWithChunkSize,
+  handleText,
+  mapFilter,
+  filter,
+  just,
+  takeWhile,
+  infiniteMVar,
+  finiteMVar,
+  vector,
+  handlingElements,
+)
+where
 
-import Potoki.Core.Prelude
-import qualified Data.ByteString.Lazy as A
-import qualified Data.ByteString.Lazy.Internal as A
+import Potoki.Core.Prelude hiding (filter, takeWhile)
+import Potoki.Core.Types
+import qualified Data.Vector as C
+import qualified Data.ByteString as D
+import qualified Data.Text.IO as A
 
 
-{-|
-Passive producer of elements.
--}
-newtype Fetch element =
-  {-|
-  Something close to a Church encoding of @IO (Maybe element)@.
-  -}
-  Fetch (forall x. x -> (element -> x) -> IO x)
-
 deriving instance Functor Fetch
 
 instance Applicative Fetch where
   pure x =
-    Fetch (\ nil just -> pure (just x))
-  (<*>) (Fetch leftFn) (Fetch rightFn) =
-    Fetch (\ nil just ->
-      join (leftFn (pure nil) (\ leftElement ->
-        rightFn nil (\ rightElement -> just (leftElement rightElement)))))
+    Fetch (pure (Just x))
+  (<*>) (Fetch leftIO) (Fetch rightIO) =
+    Fetch ((<*>) <$> leftIO <*> rightIO)
 
 instance Monad Fetch where
   return =
     pure
-  (>>=) (Fetch leftFn) rightK =
-    Fetch (\ nil just ->
-      join (leftFn (pure nil) (\ leftElement ->
-        case rightK leftElement of
-          Fetch rightFn -> rightFn nil just)))
+  (>>=) (Fetch leftIO) rightFetch =
+    Fetch $ do
+      leftFetching <- leftIO
+      case leftFetching of
+        Nothing -> return Nothing
+        Just leftElement -> case rightFetch leftElement of
+          Fetch rightIO -> rightIO
 
 instance Alternative Fetch where
   empty =
-    Fetch (\ nil just -> pure nil)
-  (<|>) (Fetch leftSignal) (Fetch rightSignal) =
-    Fetch (\ nil just -> join (leftSignal (rightSignal nil just) (pure . just)))
+    Fetch (pure Nothing)
+  (<|>) (Fetch leftIO) (Fetch rightIO) =
+    Fetch ((<|>) <$> leftIO <*> rightIO)
 
 instance MonadPlus Fetch where
   mzero =
@@ -45,6 +63,10 @@
   mplus =
     (<|>)
 
+instance MonadIO Fetch where
+  liftIO io =
+    Fetch (fmap Just io)
+
 {-# INLINABLE duplicate #-}
 duplicate :: Fetch element -> IO (Fetch element, Fetch element)
 duplicate (Fetch fetchIO) =
@@ -55,102 +77,228 @@
     notEndVar <- newTVarIO True
     let
       newFetch ownBuffer mirrorBuffer =
-        Fetch
-          (\ nil just -> do
-            join
-              (atomically
-                (mplus
-                  (do
-                    element <- readTQueue ownBuffer
-                    return (return (just element)))
-                  (do
-                    notEnd <- readTVar notEndVar
-                    if notEnd
-                      then do
-                        notFetching <- readTVar notFetchingVar
-                        guard notFetching
-                        writeTVar notFetchingVar False
-                        return
-                          (join
-                            (fetchIO
-                              (do
-                                atomically
-                                  (do
-                                    writeTVar notEndVar False
-                                    writeTVar notFetchingVar True)
-                                return nil)
-                              (\ !element -> do
-                                atomically
-                                  (do
-                                    writeTQueue mirrorBuffer element
-                                    writeTVar notFetchingVar True)
-                                return (just element))))
-                      else return (return nil)))))
+        Fetch $ do
+          fetch <- fetchIO
+          join $
+            atomically
+             (mplus
+                (do
+                   element <- readTQueue ownBuffer
+                   return $ return (Just element)
+                )
+                (do
+                   notEnd <- readTVar notEndVar
+                   if notEnd
+                     then do
+                       notFetching <- readTVar notFetchingVar
+                       guard notFetching
+                       writeTVar notFetchingVar False
+                       return $ case fetch of
+                         Nothing      -> do
+                           atomically
+                             (do
+                                writeTVar notEndVar False
+                                writeTVar notFetchingVar True
+                             )
+                           return Nothing
+                         Just !element -> do
+                           atomically
+                             (do
+                                writeTQueue mirrorBuffer element
+                                writeTVar notFetchingVar True
+                             )
+                           return $ Just element
+                     else return $ return Nothing
+                )
+             )
       leftFetch =
         newFetch leftBuffer rightBuffer
       rightFetch =
         newFetch rightBuffer leftBuffer
-      in return (leftFetch, rightFetch)
+     in return (leftFetch, rightFetch)
 
+{-# INLINABLE maybeRef #-}
+maybeRef :: IORef (Maybe a) -> Fetch a
+maybeRef refElem =
+  Fetch $ do
+    elemVal <- readIORef refElem
+    case elemVal of
+      Nothing      -> return Nothing
+      Just element -> do
+        writeIORef refElem Nothing
+        return $ Just element
+
 {-# INLINABLE list #-}
 list :: IORef [element] -> Fetch element
 list unsentListRef =
-  Fetch $ \ nil just -> atomicModifyIORef' unsentListRef $ \ case
-    (!head) : tail -> (tail, just head)
-    _ -> ([], nil)
+  Fetch $ do
+    refList <- readIORef unsentListRef
+    case refList of
+      (!headVal) : (!tailVal) -> do
+        writeIORef unsentListRef tailVal
+        return $ Just headVal
+      _              -> do
+        writeIORef unsentListRef []
+        return Nothing
 
 {-# INLINABLE firstCachingSecond #-}
 firstCachingSecond :: IORef b -> Fetch (a, b) -> Fetch a
-firstCachingSecond stateRef (Fetch bothFetchIO) =
-  Fetch $ \ nil just ->
-  join $
-  bothFetchIO
-    (return nil)
-    (\ (!first, !second) -> do
-      writeIORef stateRef second
-      return (just first))
+firstCachingSecond cacheRef (Fetch bothFetchIO) =
+  Fetch $ do
+    bothFetch <- bothFetchIO
+    case bothFetch of
+      Nothing                -> return Nothing
+      Just (!firstVal, !secondVal) -> do
+        writeIORef cacheRef secondVal
+        return $ Just firstVal
 
 {-# INLINABLE bothFetchingFirst #-}
 bothFetchingFirst :: IORef b -> Fetch a -> Fetch (a, b)
-bothFetchingFirst stateRef (Fetch firstFetchIO) =
-  Fetch $ \ nil just ->
-  join $
-  firstFetchIO
-    (return nil)
-    (\ !firstFetched -> do
-      secondCached <- readIORef stateRef
-      return (just (firstFetched, secondCached)))
+bothFetchingFirst cacheRef (Fetch firstFetchIO) =
+  Fetch $ do
+    firstFetch <- firstFetchIO
+    case firstFetch of
+      Nothing            -> return Nothing
+      Just !firstFetched -> do
+        secondCached <- readIORef cacheRef
+        return $ Just (firstFetched, secondCached)
 
+{-# INLINABLE rightHandlingLeft #-}
+rightHandlingLeft :: (left -> IO ()) -> Fetch (Either left right) -> Fetch right
+rightHandlingLeft left2IO (Fetch eitherFetchIO) =
+  Fetch $ do
+    eitherFetch <- eitherFetchIO
+    case eitherFetch of
+      Nothing    -> return Nothing
+      Just input -> case input of
+        Right rightInput -> return $ Just rightInput
+        Left  leftInput  -> left2IO leftInput $> Nothing
+
 {-# INLINABLE rightCachingLeft #-}
 rightCachingLeft :: IORef (Maybe left) -> Fetch (Either left right) -> Fetch right
-rightCachingLeft stateRef (Fetch eitherFetchIO) =
-  Fetch $ \ nil just ->
-  join $ eitherFetchIO (return nil) $ \ case
-    Right !rightInput -> return (just rightInput)
-    Left !leftInput -> writeIORef stateRef (Just leftInput) $> nil
+rightCachingLeft cacheRef =
+  rightHandlingLeft (writeIORef cacheRef . Just)
 
 {-# INLINABLE eitherFetchingRight #-}
 eitherFetchingRight :: IORef (Maybe left) -> Fetch right -> Fetch (Either left right)
-eitherFetchingRight stateRef (Fetch rightFetchIO) =
-  Fetch $ \ nil just ->
-  join $ rightFetchIO (return nil) $ \ right ->
-  atomicModifyIORef' stateRef $ \ case
-    Nothing -> (Nothing, just (Right right))
-    Just left -> (Nothing, just (Left left))
+eitherFetchingRight cacheRef (Fetch rightFetchIO) =
+  Fetch $ do
+    rightFetch <- rightFetchIO
+    case rightFetch of
+      Nothing -> return Nothing
+      Just r  -> atomicModifyIORef' cacheRef $ \ case
+        Nothing -> (Nothing, Just $ Right r)
+        Just l  -> (Nothing, Just $ Left  l)
 
-{-# INLINE ioMaybe #-}
-ioMaybe :: IO (Maybe a) -> Fetch a
-ioMaybe io =
-  Fetch $ \nil just -> maybe nil just <$> io
+{-# INLINABLE signaling #-}
+signaling :: IO () -> IO () -> Fetch a -> Fetch a
+signaling signalEnd signalElement (Fetch fetchIO) =
+  Fetch $ do
+    fetch <- fetchIO
+    case fetch of
+      Nothing      -> signalEnd $> Nothing
+      Just element -> signalElement >> return (Just element)
 
-{-# INLINE lazyByteStringRef #-}
-lazyByteStringRef :: IORef A.ByteString -> Fetch ByteString
-lazyByteStringRef ref =
-  Fetch $ \ nil just ->
-  do
-    lazyByteString <- readIORef ref
-    case lazyByteString of
-      A.Chunk chunk remainders -> do
-        writeIORef ref remainders
-        return (just chunk)
-      A.Empty -> return nil
+{-# INLINABLE ioFetch #-}
+ioFetch :: IO (Fetch a) -> Fetch a
+ioFetch fetchIO =
+  Fetch $ do
+    Fetch fetch <- fetchIO
+    fetch
+
+{-# INLINABLE handleBytes #-}
+handleBytes :: Handle -> Fetch (Either IOException ByteString)
+handleBytes =
+  handleBytesWithChunkSize ioChunkSize
+
+{-# INLINABLE handleBytesWithChunkSize #-}
+handleBytesWithChunkSize :: Int -> Handle -> Fetch (Either IOException ByteString)
+handleBytesWithChunkSize chunkSize handleVal =
+  Fetch $ do
+    chunk <- try (D.hGetSome handleVal chunkSize)
+    case chunk of
+      Right "" -> return Nothing
+      _ -> return (Just chunk)
+
+{-# INLINABLE handleText #-}
+handleText :: Handle -> Fetch (Either IOException Text)
+handleText handleVal =
+  Fetch $ do
+    chunk <- try (A.hGetChunk handleVal)
+    case chunk of
+      Right "" -> return Nothing
+      _ -> return (Just chunk)
+
+{-# INLINABLE mapFilter #-}
+mapFilter :: (input -> Maybe output) -> Fetch input -> Fetch output
+mapFilter mapping (Fetch fetchIO) =
+  Fetch $ 
+  fix $ \ doLoop -> do 
+    fetch <- fetchIO
+    case mapping <$> fetch of
+      Just (Just output) -> return (Just output)
+      Just Nothing -> doLoop
+      Nothing -> return Nothing
+
+{-# INLINABLE filter #-}
+filter :: (input -> Bool) -> Fetch input -> Fetch input
+filter predicate (Fetch fetchIO) =
+  Fetch $ 
+  fix $ \ doLoop -> do 
+    fetch <- fetchIO
+    case predicate <$> fetch of
+      Just True -> return fetch
+      Just False -> doLoop
+      Nothing -> return Nothing
+
+
+{-# INLINABLE just #-}
+just :: Fetch (Maybe element) -> Fetch element
+just (Fetch fetchIO) =
+  Fetch $ 
+  fix $ \ doLoop -> do 
+    fetch <- fetchIO
+    case fetch of
+      Just (Just element) -> return (Just element)
+      Just (Nothing) -> doLoop
+      Nothing -> return Nothing
+
+{-# INLINABLE takeWhile #-}
+takeWhile :: (element -> Bool) -> Fetch element -> Fetch element
+takeWhile predicate (Fetch fetchIO) =
+  Fetch $ do
+    fetch <- fetchIO
+    case predicate <$> fetch of
+      Just True -> return fetch
+      _ -> return Nothing
+
+{-# INLINABLE infiniteMVar #-}
+infiniteMVar :: MVar element -> Fetch element
+infiniteMVar var =
+  Fetch $ fmap Just $ takeMVar var
+
+{-# INLINABLE finiteMVar #-}
+finiteMVar :: MVar (Maybe element) -> Fetch element
+finiteMVar var =
+  Fetch $ takeMVar var
+
+{-# INLINABLE vector #-}
+vector :: IORef Int -> Vector element -> Fetch element
+vector indexRef vectorVal =
+  Fetch $ do
+    indexVal <- readIORef indexRef
+    if indexVal < C.length vectorVal
+      then do
+        writeIORef indexRef (succ indexVal)
+        return (Just (C.unsafeIndex vectorVal indexVal))
+      else return Nothing
+
+{-# INLINABLE handlingElements #-}
+handlingElements :: (element -> IO ()) -> Fetch element -> Fetch element
+handlingElements xRay (Fetch fetchIO) =
+  Fetch $ do
+    mbElement <- fetchIO
+    case mbElement of
+      Just element -> xRay element $> mbElement
+      Nothing -> return Nothing
+    
diff --git a/library/Potoki/Core/IO.hs b/library/Potoki/Core/IO.hs
--- a/library/Potoki/Core/IO.hs
+++ b/library/Potoki/Core/IO.hs
@@ -1,40 +1,42 @@
-module Potoki.Core.IO where
+module Potoki.Core.IO (
+  produceAndConsume,
+  produceAndTransformAndConsume,
+  produce,
+  consume,
+  transformList,
+) where
 
 import Potoki.Core.Prelude
+import Potoki.Core.Types
 import qualified Potoki.Core.Produce as A
 import qualified Potoki.Core.Consume as B
-import qualified Potoki.Core.Transform as C
-import qualified Potoki.Core.Fetch as D
+import qualified Acquire.IO as C
 
 
-produceAndConsume :: A.Produce input -> B.Consume input output -> IO output
-produceAndConsume (A.Produce produce) (B.Consume consume) =
-  do
-    (fetch, kill) <- produce
-    consume fetch <* kill
-
-produceAndTransformAndConsume :: A.Produce input -> C.Transform input anotherInput -> B.Consume anotherInput output -> IO output
-produceAndTransformAndConsume (A.Produce produce) (C.Transform transform) (B.Consume consume) =
-  do
-    (fetch, kill) <- produce
-    (transform fetch >>= consume) <* kill
+produceAndConsume :: Produce input -> Consume input output -> IO output
+produceAndConsume (Produce produceAcquire) (Consume consumeIO) =
+  C.acquire produceAcquire consumeIO
 
-produce :: A.Produce input -> forall x. IO x -> (input -> IO x) -> IO x
-produce (A.Produce produce) stop emit =
-  do
-    (D.Fetch fetchIO, kill) <- produce
-    fix (\ loop -> join (fetchIO stop (\ element -> emit element >> loop))) <* kill
+produceAndTransformAndConsume :: Produce input -> Transform input anotherInput -> Consume anotherInput output -> IO output
+produceAndTransformAndConsume (Produce produceAcquire) (Transform transformAcquire) (Consume consumeIO) =
+  C.acquire (produceAcquire >>= transformAcquire) consumeIO
 
-consume :: (forall x. x -> (input -> x) -> IO x) -> B.Consume input output -> IO output
-consume fetch (B.Consume consume) =
-  consume (D.Fetch fetch)
+produce :: Produce input -> forall x. IO x -> (input -> IO x) -> IO x
+produce (Produce produceAcquire) stop emit =
+  C.acquire produceAcquire $ \ (Fetch fetchIO) ->
+    fix $ \ doLoop -> do
+      fetch <- fetchIO
+      case fetch of
+        Nothing      -> stop
+        Just element -> emit element >> doLoop
 
-{-| Fetch all the elements running the provided handler on them -}
-fetchAndHandleAll :: D.Fetch element -> IO () -> (element -> IO ()) -> IO ()
-fetchAndHandleAll (D.Fetch fetchIO) onEnd onElement =
-  fix (\ loop -> join (fetchIO onEnd (\ element -> onElement element >> loop)))
+consume :: IO (Maybe input) -> Consume input output -> IO output
+consume fetchIO (Consume consumeIO) =
+  consumeIO $ Fetch fetchIO
 
-{-| Fetch just one element -}
-fetch :: D.Fetch element -> IO (Maybe element)
-fetch (D.Fetch fetchIO) =
-  fetchIO Nothing Just
+transformList :: Transform a b -> [a] -> IO [b]
+transformList transform inputList =
+  produceAndTransformAndConsume
+    (A.list inputList)
+    transform
+    (B.list)
diff --git a/library/Potoki/Core/IO/Fetch.hs b/library/Potoki/Core/IO/Fetch.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/IO/Fetch.hs
@@ -0,0 +1,22 @@
+module Potoki.Core.IO.Fetch where
+
+import Potoki.Core.Prelude
+import Potoki.Core.Types
+
+{-| Fetch all the elements running the provided handler on them -}
+fetchAndHandleAll :: Fetch element -> IO () -> (element -> IO ()) -> IO ()
+fetchAndHandleAll (Fetch fetchIO) onEnd onElement =
+  fix $ \ doLoop -> do
+    fetch <- fetchIO
+    case fetch of
+      Nothing      -> onEnd
+      Just element -> onElement element >> doLoop
+
+{-| Fetch and handle just one element -}
+fetchAndHandle :: Fetch element -> IO a -> (element -> IO a) -> IO a
+fetchAndHandle (Fetch fetchIO) onEnd onElement =
+  do
+    fetch <- fetchIO
+    case fetch of
+      Nothing      -> onEnd
+      Just element -> onElement element
diff --git a/library/Potoki/Core/Prelude.hs b/library/Potoki/Core/Prelude.hs
--- a/library/Potoki/Core/Prelude.hs
+++ b/library/Potoki/Core/Prelude.hs
@@ -1,6 +1,9 @@
 module Potoki.Core.Prelude
 ( 
   module Exports,
+  ioChunkSize,
+  textString,
+  unsnoc,
 )
 where
 
@@ -32,7 +35,7 @@
 import Data.Ix as Exports
 import Data.List as Exports hiding (sortOn, isSubsequenceOf, uncons, concat, foldr, foldl1, maximum, minimum, product, sum, all, and, any, concatMap, elem, foldl, foldr1, notElem, or, find, maximumBy, minimumBy, mapAccumL, mapAccumR, foldl')
 import Data.Maybe as Exports
-import Data.Monoid as Exports
+import Data.Monoid as Exports hiding (Last(..), First(..))
 import Data.Ord as Exports
 import Data.Proxy as Exports
 import Data.Ratio as Exports
@@ -56,7 +59,7 @@
 import Prelude as Exports hiding (concat, foldr, mapM_, sequence_, foldl1, maximum, minimum, product, sum, all, and, any, concatMap, elem, foldl, foldr1, notElem, or, mapM, sequence, id, (.))
 import System.Environment as Exports
 import System.Exit as Exports
-import System.IO as Exports (Handle, hClose)
+import System.IO as Exports
 import System.IO.Error as Exports
 import System.IO.Unsafe as Exports
 import System.Mem as Exports
@@ -68,10 +71,6 @@
 import Text.Read as Exports (Read(..), readMaybe, readEither)
 import Unsafe.Coerce as Exports
 
--- bytestring
--------------------------
-import Data.ByteString as Exports (ByteString)
-
 -- profunctors
 -------------------------
 import Data.Profunctor.Unsafe as Exports
@@ -81,3 +80,54 @@
 -- stm
 -------------------------
 import Control.Concurrent.STM as Exports
+
+-- acquire
+-------------------------
+import Acquire.Acquire as Exports
+
+-- text
+-------------------------
+import Data.Text as Exports (Text)
+
+-- bytestring
+-------------------------
+import Data.ByteString as Exports (ByteString)
+
+-- unordered-containers
+-------------------------
+import Data.HashMap.Strict as Exports (HashMap)
+
+-- vector
+-------------------------
+import Data.Vector as Exports (Vector)
+
+-- hashable
+-------------------------
+import Data.Hashable as Exports (Hashable)
+
+--------------------------------------------------------------------------------
+
+import qualified Data.Text as A
+
+{-# NOINLINE ioChunkSize #-}
+ioChunkSize :: Int
+ioChunkSize =
+  shiftL 2 12
+
+textString :: Text -> String
+textString =
+  A.unpack
+
+{-# INLINABLE unsnoc #-}
+unsnoc :: [a] -> Maybe ([a], a)
+unsnoc listVal =
+  case process listVal of
+    (initVal, lastMaybe) -> fmap (\ lastVal -> (initVal, lastVal)) lastMaybe
+  where
+    process listVal' =
+      case listVal' of
+        headVal : tailVal -> case tailVal of
+          [] -> ([], Just headVal)
+          _ -> case process tailVal of
+            (initVal, lastMaybe) -> (headVal : initVal, lastMaybe)
+        _ -> ([], Nothing)
diff --git a/library/Potoki/Core/Produce.hs b/library/Potoki/Core/Produce.hs
--- a/library/Potoki/Core/Produce.hs
+++ b/library/Potoki/Core/Produce.hs
@@ -1,57 +1,191 @@
-module Potoki.Core.Produce where
+module Potoki.Core.Produce
+(
+  Produce(..),
+  list,
+  transform,
+  vector,
+  hashMapRows,
+  fileBytes,
+  fileBytesAtOffset,
+  fileText,
+  stdinBytes,
+  directoryContents,
+  finiteMVar,
+  infiniteMVar,
+)
+where
 
 import Potoki.Core.Prelude
+import Potoki.Core.Types
 import qualified Potoki.Core.Fetch as A
-import qualified Potoki.Core.Transform.Types as B
-import qualified Data.ByteString.Lazy as C
+import qualified Data.HashMap.Strict as B
+import qualified Data.Vector as C
+import qualified System.Directory as G
+import qualified Acquire.Acquire as M
 
 
-{-|
-Passive producer of elements with support for early termination.
-
-Automates the management of resources.
--}
-newtype Produce element =
-  Produce (IO (A.Fetch element, IO ()))
-
 deriving instance Functor Produce
 
 instance Applicative Produce where
-  pure x =
-    list [x]
-  (<*>) (Produce leftIO) (Produce rightIO) =
-    Produce $ do
-      (leftFetch, leftKill) <- leftIO
-      (rightFetch, rightKill) <- rightIO
-      return (leftFetch <*> rightFetch, leftKill >> rightKill)
+  pure x = Produce $ do
+    refX <- liftIO (newIORef (Just x))
+    return (A.maybeRef refX)
+  (<*>) (Produce leftAcquire) (Produce rightAcquire) =
+    Produce ((<*>) <$> leftAcquire <*> rightAcquire)
 
 instance Alternative Produce where
   empty =
-    Produce (pure (empty, pure ()))
-  (<|>) (Produce leftIO) (Produce rightIO) =
-    Produce $ do
-      (leftFetch, leftKill) <- leftIO
-      (rightFetch, rightKill) <- rightIO
-      return (leftFetch <|> rightFetch, leftKill >> rightKill)
+    Produce (pure empty)
+  (<|>) (Produce leftAcquire) (Produce rightAcquire) =
+    Produce ((<|>) <$> leftAcquire <*> rightAcquire)
 
+instance Monad Produce where
+  return = pure
+  (>>=) (Produce (Acquire io1)) k2 =
+    Produce $ Acquire $ do
+      (fetch1, release1) <- io1
+      release2Ref <- newIORef (return ())
+      let
+        fetch2 input1 =
+          case k2 input1 of
+            Produce (Acquire io2) ->
+              A.ioFetch $ do
+                join (readIORef release2Ref)
+                (fetch2', release2') <- io2
+                writeIORef release2Ref release2'
+                return fetch2'
+        release3 =
+          join (readIORef release2Ref) >> release1
+        in return (fetch1 >>= fetch2, release3)
+
+instance MonadIO Produce where
+  liftIO io =
+    Produce (return (liftIO io))
+
 {-# INLINABLE list #-}
 list :: [input] -> Produce input
-list list =
-  Produce $ do
-    unsentListRef <- newIORef list
-    return (A.list unsentListRef, return ())
+list inputList =
+  Produce $ liftIO (A.list <$> newIORef inputList)
 
 {-# INLINE transform #-}
-transform :: B.Transform input output -> Produce input -> Produce output
-transform (B.Transform transformIO) (Produce produceIO) =
+transform :: Transform input output -> Produce input -> Produce output
+transform (Transform transformAcquire) (Produce produceAcquire) =
   Produce $ do
-    (fetch, kill) <- produceIO
-    newFetch <- transformIO fetch
-    return (newFetch, kill)
+    fetch <- produceAcquire
+    transformAcquire fetch
 
-{-# INLINE lazyByteString #-}
-lazyByteString :: C.ByteString -> Produce ByteString
-lazyByteString lbs =
-  Produce $ do
-    ref <- newIORef lbs
-    return (A.lazyByteStringRef ref, return ())
+{-# INLINE vector #-}
+vector :: Vector input -> Produce input
+vector vectorVal =
+  Produce $ M.Acquire $ do
+    indexRef <- newIORef 0
+    let
+      fetch =
+        A.Fetch $ do
+          indexVal <- readIORef indexRef
+          writeIORef indexRef $! succ indexVal
+          return $ (C.!?) vectorVal indexVal
+      in return (fetch, return ())
+
+{-# INLINE hashMapRows #-}
+hashMapRows :: HashMap a b -> Produce (a, b)
+hashMapRows =
+  list . B.toList
+
+{-|
+Read from a file by path.
+
+* Exception-free
+* Automatic resource management
+-}
+{-# INLINABLE fileBytes #-}
+fileBytes :: FilePath -> Produce (Either IOException ByteString)
+fileBytes path =
+  accessingHandle (openBinaryFile path ReadMode) A.handleBytes
+
+{-|
+Read from a file by path.
+
+* Exception-free
+* Automatic resource management
+-}
+{-# INLINABLE fileBytesAtOffset #-}
+fileBytesAtOffset :: FilePath -> Int -> Produce (Either IOException ByteString)
+fileBytesAtOffset path offset =
+  accessingHandle acquire A.handleBytes
+  where
+    acquire =
+      do
+        handleVal <- openBinaryFile path ReadMode
+        hSeek handleVal AbsoluteSeek (fromIntegral offset)
+        return handleVal
+
+{-# INLINABLE accessingHandle #-}
+accessingHandle :: IO Handle -> (Handle -> A.Fetch (Either IOException a)) -> Produce (Either IOException a)
+accessingHandle acquireHandle fetch =
+  Produce $ M.Acquire (catchIOError normal failing)
+  where
+    normal =
+      do
+        handleVal <- acquireHandle
+        return (fetch handleVal, catchIOError (hClose handleVal) (const (return ())))
+    failing exception =
+      return (pure (Left exception), return ())
+
+{-# INLINABLE stdinBytes #-}
+stdinBytes :: Produce (Either IOException ByteString)
+stdinBytes =
+  Produce $ M.Acquire (return (A.handleBytes stdin, return ()))
+
+{-|
+Sorted subpaths of the directory.
+-}
+{-# INLINABLE directoryContents #-}
+directoryContents :: FilePath -> Produce (Either IOException FilePath)
+directoryContents path =
+  Produce $ M.Acquire (catchIOError success failure)
+  where
+    success =
+      do
+        subPaths <- G.listDirectory path
+        ref <- newIORef (map (Right . mappend path . (:) '/') (sort subPaths))
+        return (A.list ref, return ())
+    failure exception =
+      return (pure (Left exception), return ())
+
+{-|
+Read from a file by path.
+
+* Exception-free
+* Automatic resource management
+-}
+{-# INLINABLE fileText #-}
+fileText :: FilePath -> Produce (Either IOException Text)
+fileText path =
+  Produce $ M.Acquire (catchIOError success failure)
+  where
+    success =
+      do
+        handleVal <- openFile path ReadMode
+        return (A.handleText handleVal, catchIOError (hClose handleVal) (const (return ())))
+    failure exception =
+      return (pure (Left exception), return ())
+
+{-|
+Read from MVar.
+Nothing gets interpreted as the end of input.
+-}
+{-# INLINE finiteMVar #-}
+finiteMVar :: MVar (Maybe element) -> Produce element
+finiteMVar var =
+  Produce $ M.Acquire (return (A.finiteMVar var, return ()))
+
+{-|
+Read from MVar.
+Never stops.
+-}
+{-# INLINE infiniteMVar #-}
+infiniteMVar :: MVar element -> Produce element
+infiniteMVar var =
+  Produce $ M.Acquire (return (A.infiniteMVar var, return ()))
+    
diff --git a/library/Potoki/Core/Transform.hs b/library/Potoki/Core/Transform.hs
--- a/library/Potoki/Core/Transform.hs
+++ b/library/Potoki/Core/Transform.hs
@@ -4,143 +4,47 @@
   consume,
   produce,
   mapFetch,
-  executeIO,
+  -- * Basics
+  ioTransform,
   take,
+  takeWhile,
+  drop,
+  mapFilter,
+  filter,
+  just,
+  list,
+  vector,
+  distinctBy,
+  distinct,
+  executeIO,
+  mapInIO,
+  -- * ByteString
+  module Potoki.Core.Transform.ByteString,
+  -- * State
+  R.runState,
+  R.execState,
+  R.evalState,
+  -- * Parsing
+  A.parseBytes,
+  A.parseText,
+  -- * Concurrency
+  N.bufferize,
+  N.concurrently,
+  N.async,
+  -- * File IO
+  deleteFile,
+  appendBytesToFile,
+  writeTextToFile,
+  -- * Debugging
+  traceWithCounter,
 )
 where
 
-import Potoki.Core.Prelude hiding (take)
-import Potoki.Core.Transform.Types
-import qualified Potoki.Core.Fetch as A
-import qualified Potoki.Core.Consume as C
-import qualified Potoki.Core.Produce as D
-
-
-instance Category Transform where
-  id =
-    Transform return
-  (.) (Transform leftFetchIO) (Transform rightFetchIO) =
-    Transform (leftFetchIO <=< rightFetchIO)
-
-instance Profunctor Transform where
-  dimap inputMapping outputMapping (Transform fetchIO) =
-    Transform (\ inputFetch -> (fmap . fmap) outputMapping (fetchIO (fmap inputMapping inputFetch)))
-
-instance Choice Transform where
-  right' (Transform rightTransformIO) =
-    Transform $ \ eitherFetch -> do
-      fetchedLeftMaybeRef <- newIORef Nothing
-      rightFetchMaybeRef <- newIORef Nothing
-      return $ A.Fetch $ \ nil just -> do
-        A.Fetch rightFetchIO <- do
-          rightFetchMaybe <- readIORef rightFetchMaybeRef
-          case rightFetchMaybe of
-            Just rightFetch -> return rightFetch
-            Nothing -> do
-              rightFetch <- rightTransformIO (A.rightCachingLeft fetchedLeftMaybeRef eitherFetch)
-              writeIORef rightFetchMaybeRef (Just rightFetch)
-              return rightFetch
-        join $ rightFetchIO
-          (do
-            fetchedLeftMaybe <- readIORef fetchedLeftMaybeRef
-            case fetchedLeftMaybe of
-              Just fetchedLeft -> do
-                writeIORef fetchedLeftMaybeRef Nothing
-                writeIORef rightFetchMaybeRef Nothing
-                return (just (Left fetchedLeft))
-              Nothing -> return nil)
-          (\ right -> return (just (Right right)))
-
-instance Strong Transform where
-  first' (Transform firstTransformIO) =
-    Transform $ \ bothFetch -> do
-      stateRef <- newIORef undefined
-      firstFetch <- firstTransformIO (A.firstCachingSecond stateRef bothFetch)
-      return $ A.bothFetchingFirst stateRef firstFetch
-
-instance Arrow Transform where
-  arr fn =
-    Transform (pure . fmap fn)
-  first =
-    first'
-
-instance ArrowChoice Transform where
-  left =
-    left'
-
-{-# INLINE consume #-}
-consume :: C.Consume input output -> Transform input output
-consume (C.Consume runFetch) =
-  Transform $ \ (A.Fetch fetch) -> do
-    stoppedRef <- newIORef False
-    return $ A.Fetch $ \ nil just -> do
-      stopped <- readIORef stoppedRef
-      if stopped
-        then return nil
-        else do
-          emittedRef <- newIORef False
-          output <-
-            runFetch $ A.Fetch $ \ inputNil inputJust ->
-            join
-              (fetch
-                (do
-                  writeIORef stoppedRef True
-                  return inputNil)
-                (\ !input -> do
-                  writeIORef emittedRef True
-                  return (inputJust input)))
-          stopped <- readIORef stoppedRef
-          if stopped
-            then do
-              emitted <- readIORef emittedRef
-              if emitted
-                then return (just output)
-                else return nil
-            else return (just output)
-
-{-# INLINABLE produce #-}
-produce :: (input -> D.Produce output) -> Transform input output
-produce inputToProduce =
-  Transform $ \ (A.Fetch inputFetchIO) -> do
-    stateRef <- newIORef Nothing
-    return $ A.Fetch $ \ nil just -> fix $ \ loop -> do
-      state <- readIORef stateRef
-      case state of
-        Just (A.Fetch outputFetchIO, kill) ->
-          join $ outputFetchIO
-            (kill >> writeIORef stateRef Nothing >> loop)
-            (return . just)
-        Nothing ->
-          join $ inputFetchIO (return nil) $ \ !input -> do
-            case inputToProduce input of
-              D.Produce produceIO -> do
-                fetchAndKill <- produceIO
-                writeIORef stateRef (Just fetchAndKill)
-                loop
-
-{-# INLINE mapFetch #-}
-mapFetch :: (A.Fetch a -> A.Fetch b) -> Transform a b
-mapFetch mapping =
-  Transform $ return . mapping
-
-{-|
-Execute the IO action.
--}
-{-# INLINE executeIO #-}
-executeIO :: Transform (IO a) a
-executeIO =
-  mapFetch $ \ (A.Fetch fetchIO) -> A.Fetch $ \ nil just ->
-  join (fetchIO (return nil) (fmap just))
+import Potoki.Core.Types
+import Potoki.Core.Transform.Basic
+import Potoki.Core.Transform.FileIO
+import Potoki.Core.Transform.ByteString
+import qualified Potoki.Core.Transform.Attoparsec as A
+import qualified Potoki.Core.Transform.Concurrency as N
+import qualified Potoki.Core.Transform.State as R
 
-{-# INLINE take #-}
-take :: Int -> Transform input input
-take amount =
-  Transform $ \ (A.Fetch fetchIO) -> do
-    countRef <- newIORef amount
-    return $ A.Fetch $ \ nil just -> do
-      count <- readIORef countRef
-      if count > 0
-        then do
-          writeIORef countRef $! pred count
-          fetchIO nil just
-        else return nil
diff --git a/library/Potoki/Core/Transform/Attoparsec.hs b/library/Potoki/Core/Transform/Attoparsec.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Transform/Attoparsec.hs
@@ -0,0 +1,83 @@
+module Potoki.Core.Transform.Attoparsec
+where
+
+import Potoki.Core.Prelude hiding (take, takeWhile, filter, drop)
+import Potoki.Core.Types
+import qualified Potoki.Core.Fetch as A
+import qualified Data.Attoparsec.ByteString as K
+import qualified Data.Attoparsec.Text as L
+import qualified Data.Attoparsec.Types as M
+import qualified Acquire.Acquire as N
+
+
+{-# INLINE mapWithParseResult #-}
+mapWithParseResult :: forall input parsed. (Monoid input, Eq input) => (input -> M.IResult input parsed) -> Transform input (Either Text parsed)
+mapWithParseResult inputToResult =
+  Transform $ \inputFetch -> N.Acquire $ do
+    unconsumedRef <- newIORef mempty
+    finishedRef <- newIORef False
+    return (A.Fetch (fetchParsed inputFetch finishedRef unconsumedRef), return ())
+  where
+    fetchParsed :: A.Fetch input -> IORef Bool -> IORef input -> IO (Maybe (Either Text parsed))
+    fetchParsed (A.Fetch inputFetchIO) finishedRef unconsumedRef =
+      do
+        finished <- readIORef finishedRef
+        if finished
+          then return Nothing
+          else do
+            unconsumed <- readIORef unconsumedRef
+            if unconsumed == mempty
+              then
+                inputFetchIO >>= \case
+                  Nothing -> return Nothing
+                  Just input -> do
+                    if input == mempty
+                      then return Nothing
+                      else matchResult (inputToResult input)
+              else do
+                writeIORef unconsumedRef mempty
+                matchResult (inputToResult unconsumed)
+      where
+        matchResult :: M.IResult input parsed -> IO (Maybe (Either Text parsed))
+        matchResult =
+          \case
+            M.Partial inputToResultVal ->
+              consumeVal inputToResultVal
+            M.Done unconsumed parsed ->
+              do
+                writeIORef unconsumedRef unconsumed
+                return (Just (Right parsed))
+            M.Fail unconsumed contexts message ->
+              do
+                writeIORef unconsumedRef unconsumed
+                writeIORef finishedRef True
+                return (Just (Left resultMessage))
+              where
+                resultMessage =
+                  if null contexts
+                    then fromString message
+                    else fromString (showString (intercalate " > " contexts) (showString ": " message))
+        consumeVal inputToResultVal' =
+          inputFetchIO >>= \case
+            Nothing -> do
+              writeIORef finishedRef True
+              matchResult (inputToResultVal' mempty)
+            Just input -> do
+              when (input == mempty) (writeIORef finishedRef True)
+              matchResult (inputToResultVal' input)
+
+{-|
+Lift an Attoparsec ByteString parser.
+-}
+{-# INLINE parseBytes #-}
+parseBytes :: K.Parser parsed -> Transform ByteString (Either Text parsed)
+parseBytes parser =
+  mapWithParseResult (K.parse parser)
+
+{-|
+Lift an Attoparsec Text parser.
+-}
+{-# INLINE parseText #-}
+parseText :: L.Parser parsed -> Transform Text (Either Text parsed)
+parseText parser =
+  mapWithParseResult (L.parse parser)
diff --git a/library/Potoki/Core/Transform/Basic.hs b/library/Potoki/Core/Transform/Basic.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Transform/Basic.hs
@@ -0,0 +1,231 @@
+module Potoki.Core.Transform.Basic
+where
+
+import Potoki.Core.Prelude hiding (take, takeWhile, filter, drop)
+import Potoki.Core.Types
+import qualified Potoki.Core.Fetch as A
+import qualified Data.HashSet as C
+import qualified Data.Vector as P
+import qualified Acquire.Acquire as M
+
+
+{-# INLINE mapFilter #-}
+mapFilter :: (input -> Maybe output) -> Transform input output
+mapFilter mapping =
+  Transform (return . A.mapFilter mapping)
+
+{-# INLINE filter #-}
+filter :: (input -> Bool) -> Transform input input
+filter predicate =
+  Transform (pure . A.filter predicate)
+
+{-# INLINE just #-}
+just :: Transform (Maybe input) input
+just =
+  Transform (pure . A.just)
+
+{-# INLINE takeWhile #-}
+takeWhile :: (input -> Bool) -> Transform input input
+takeWhile predicate =
+  Transform (pure . A.takeWhile predicate)
+
+{-# INLINE drop #-}
+drop :: Int -> Transform input input
+drop amount =
+  Transform $ \ (A.Fetch fetchIO) -> M.Acquire $ do
+    countRef <- newIORef amount
+    return $ (, return ()) $ 
+      A.Fetch $ fix $ \ doLoop -> do
+        count <- readIORef countRef
+        if count > 0
+          then do
+            writeIORef countRef $! pred count
+            doLoop
+          else fetchIO
+
+{-# INLINE list #-}
+list :: Transform [a] a
+list =
+  Transform $ \ (A.Fetch fetchListIO) -> M.Acquire $ do
+    bufferRef <- newIORef []
+    return $ (, return ()) $ 
+      A.Fetch $ do
+        buffer <- readIORef bufferRef
+        case buffer of
+          headVal : tailVal -> do
+            writeIORef bufferRef tailVal
+            return (Just headVal)
+          _ ->
+            let
+              fetchElementIO = do
+                fetchListIO >>= \case
+                  Nothing -> return Nothing
+                  Just (headVal : tailVal) -> do
+                    writeIORef bufferRef tailVal
+                    return (Just headVal)
+                  _ -> do
+                    writeIORef bufferRef []
+                    return Nothing
+              in fetchElementIO
+
+{-# INLINABLE vector #-}
+vector :: Transform (Vector a) a
+vector =
+  Transform $ \ (A.Fetch fetchVectorIO) -> M.Acquire $ do
+    indexRef <- newIORef 0
+    vectorRef <- newIORef mempty
+    return $ (, return ()) $ 
+      A.Fetch $ fix $ \ doLoop -> do
+        vectorVal <- readIORef vectorRef
+        indexVal <- readIORef indexRef
+        if indexVal < P.length vectorVal
+          then do
+            writeIORef indexRef (succ indexVal)
+            return (Just (P.unsafeIndex vectorVal indexVal))
+          else fetchVectorIO >>= \case 
+            Just vectorVal' -> do
+              writeIORef vectorRef vectorVal'
+              writeIORef indexRef 0
+              doLoop
+            Nothing -> return Nothing
+
+{-# INLINE distinctBy #-}
+distinctBy :: (Eq comparable, Hashable comparable) => (element -> comparable) -> Transform element element
+distinctBy f =
+  Transform $ \ (A.Fetch fetch) -> M.Acquire $ do
+    stateRef <- newIORef mempty
+    return $ (, return ()) $ 
+      A.Fetch $ fix $ \ doLoop -> 
+        fetch >>= \case 
+          Nothing -> return Nothing
+          Just input -> do
+            let comparable = f input
+            !set <- readIORef stateRef
+            if C.member comparable set
+              then doLoop
+              else do
+                writeIORef stateRef $! C.insert comparable set
+                return (Just input)
+
+{-# INLINE distinct #-}
+distinct :: (Eq element, Hashable element) => Transform element element
+distinct = distinctBy id
+
+{-# INLINE mapInIO #-}
+mapInIO :: (a -> IO b) -> Transform a b
+mapInIO io =
+  Transform $ \ (A.Fetch fetch) -> M.Acquire $ 
+  return $ (, return ()) $ A.Fetch $ 
+  join $ (sequence . fmap io) <$> fetch
+
+{-# INLINE ioTransform #-}
+ioTransform :: IO (Transform a b) -> Transform a b
+ioTransform io =
+  Transform $ \ fetch -> do
+    Transform acquire <- liftIO io
+    acquire fetch
+
+{-|
+Useful for debugging
+-}
+traceWithCounter :: (Int -> String) -> Transform a a
+traceWithCounter showFunc =
+  ioTransform $ do
+    counter <- newIORef 0
+    return $ mapInIO $ \ x -> do
+      n <- atomicModifyIORef' counter (\ n -> (succ n, n))
+      putStrLn (showFunc n)
+      return x
+
+{-# INLINE consume #-}
+consume :: Consume input output -> Transform input output
+consume (Consume runFetch) =
+  Transform $ \ (Fetch inputIO) -> do
+    stoppedRef <- liftIO $ newIORef False
+    return $ Fetch $ do
+      stopped <- readIORef stoppedRef
+      if stopped
+        then do
+          writeIORef stoppedRef False
+          return Nothing
+        else do
+          emittedRef <- newIORef False
+          output <- runFetch $ Fetch $ do
+            input <- inputIO
+            case input of
+              Nothing     -> do
+                writeIORef stoppedRef True
+                return Nothing
+              Just element -> do
+                writeIORef emittedRef True
+                return $ Just element
+          checkStopped <- readIORef stoppedRef
+          if checkStopped
+            then do
+              emitted <- readIORef emittedRef
+              if emitted
+                then return $ Just output
+                else do
+                  writeIORef stoppedRef False
+                  return Nothing
+            else return $ Just output
+
+{-# INLINABLE produce #-}
+produce :: (input -> Produce output) -> Transform input output
+produce inputToProduce =
+  Transform $ \ (Fetch inputFetchIO) -> do
+    stateRef <- liftIO $ newIORef Nothing
+    return $ Fetch $ fix $ \ doLoop -> do
+      state <- readIORef stateRef
+      case state of
+        Just (Fetch outputFetchIO, kill) ->
+          do
+            outputFetchResult <- outputFetchIO
+            case outputFetchResult of
+              Just x -> return (Just x)
+              Nothing -> do
+                kill
+                writeIORef stateRef Nothing
+                doLoop
+        Nothing ->
+          do
+            inputFetchResult <- inputFetchIO
+            case inputFetchResult of
+              Just input -> do
+                case inputToProduce input of
+                  Produce (Acquire produceIO) -> do
+                    fetchAndKill <- produceIO
+                    writeIORef stateRef (Just fetchAndKill)
+                    doLoop
+              Nothing -> return Nothing
+
+{-# INLINE mapFetch #-}
+mapFetch :: (Fetch a -> Fetch b) -> Transform a b
+mapFetch mapping =
+  Transform $ return . mapping
+
+{-|
+Execute the IO action.
+-}
+{-# INLINE executeIO #-}
+executeIO :: Transform (IO a) a
+executeIO =
+  mapFetch $ \ (Fetch fetchIO) -> Fetch (fetchIO >>= sequence)
+
+{-# INLINE take #-}
+take :: Int -> Transform input input
+take amount
+  | amount <= 0 =
+    Transform $ \ _ -> return $ Fetch $ return Nothing
+  | otherwise   =
+    Transform $ \ (Fetch fetchIO) -> do
+      countRef <- liftIO $ newIORef amount
+      return $ Fetch $ do
+        count <- readIORef countRef
+        if count > 0
+          then do
+            modifyIORef countRef pred
+            fetchIO
+          else
+            return Nothing
+      
diff --git a/library/Potoki/Core/Transform/ByteString.hs b/library/Potoki/Core/Transform/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Transform/ByteString.hs
@@ -0,0 +1,58 @@
+module Potoki.Core.Transform.ByteString
+where
+
+import Potoki.Core.Prelude hiding (filter)
+import Potoki.Core.Transform.Basic
+import Potoki.Core.Transform.Instances ()
+import Potoki.Core.Types
+import qualified Potoki.Core.Fetch as A
+import qualified Potoki.Core.Produce as H
+import qualified Ptr.Poking as C
+import qualified Ptr.ByteString as D
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Builder as E
+import qualified Data.ByteString.Lazy as F
+import qualified Acquire.Acquire as M
+
+
+{-# INLINE builderChunks #-}
+builderChunks :: Transform E.Builder ByteString
+builderChunks =
+  produce (H.list . F.toChunks . E.toLazyByteString)
+
+{-|
+Convert freeform bytestring chunks into chunks,
+which are strictly separated by newline no matter how long they may be.
+-}
+extractLines :: Transform ByteString ByteString
+extractLines =
+  lineList >>> filter (not . null) >>> list
+  where
+    lineList =
+      Transform $ \ (A.Fetch fetchIO) -> M.Acquire $ do
+        stateRef <- newIORef Nothing
+        return $ (, return ()) $  A.Fetch $ fetchIO >>= \case
+          Nothing -> (do
+            state <- readIORef stateRef
+            case state of
+              Just poking -> do
+                writeIORef stateRef Nothing
+                return (Just [D.poking poking])
+              Nothing -> return Nothing)
+          Just chunk -> (
+            case B.split 10 chunk of
+              firstInput : tailVal -> do
+                state <- readIORef stateRef
+                let
+                  newPoking =
+                    fold state <> C.bytes firstInput
+                  in case unsnoc tailVal of
+                    Just (initVal, lastVal) ->
+                      do
+                        writeIORef stateRef (Just (C.bytes lastVal))
+                        return (Just (D.poking newPoking : initVal))
+                    Nothing ->
+                      do
+                        writeIORef stateRef (Just newPoking)
+                        return (Just [])
+              _ -> return (Just []))
diff --git a/library/Potoki/Core/Transform/Concurrency.hs b/library/Potoki/Core/Transform/Concurrency.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Transform/Concurrency.hs
@@ -0,0 +1,103 @@
+module Potoki.Core.Transform.Concurrency
+(
+  bufferize,
+  concurrently,
+  async,
+)
+where
+
+import Potoki.Core.Prelude hiding (take, takeWhile, filter)
+import Potoki.Core.Transform.Instances ()
+import Potoki.Core.Types
+import qualified Potoki.Core.Fetch as A
+import qualified Acquire.Acquire as M
+
+
+{-# INLINE bufferize #-}
+bufferize :: Int -> Transform element element
+bufferize = undefined
+{-
+bufferize size =
+  Transform $ \ (A.Fetch fetch) -> M.Acquire $ do
+    (inChan, outChan) <- B.newChan size
+    forkIO $ fix $ \ doLoop ->
+      fetch >>= \case
+        Nothing -> B.writeChan inChan Nothing
+        Just !element -> B.writeChan inChan (Just element) >> doLoop
+    return $ (A.Fetch $ B.readChan outChan, return ())
+-}
+
+{-|
+Identity Transform, which ensures that the inputs are fetched synchronously.
+
+Useful for concurrent transforms.
+-}
+{-# INLINABLE sync #-}
+sync :: Transform a a
+sync =
+  Transform $ \ (A.Fetch fetch) -> M.Acquire $ do
+    activeVar <- newMVar True
+    return $ (, return ()) $ A.Fetch $ do
+      active <- takeMVar activeVar
+      if active
+        then fetch >>= \case
+          Just !element -> do
+            putMVar activeVar True
+            return (Just element)
+          Nothing -> do
+            putMVar activeVar False
+            return Nothing
+        else do
+          putMVar activeVar False
+          return Nothing
+
+{-|
+Execute the transform on the specified amount of threads.
+The order of the outputs produced is indiscriminate.
+-}
+{-# INLINABLE concurrently #-}
+concurrently :: Int -> Transform input output -> Transform input output
+concurrently workersAmount transform =
+  if workersAmount == 1
+    then transform
+    else
+      sync >>>
+      concurrentlyUnsafe workersAmount transform
+
+{-# INLINE concurrentlyUnsafe #-}
+concurrentlyUnsafe :: Int -> Transform input output -> Transform input output
+concurrentlyUnsafe workersAmount (Transform syncTransformIO) = 
+  Transform $ \ fetch -> M.Acquire $ do
+    outChan <- newEmptyMVar
+    replicateM_ workersAmount $ forkIO $ do
+      let runAcquire (M.Acquire io) = io
+      (A.Fetch fetchIO, _) <- runAcquire $ syncTransformIO fetch
+      fix $ \ doLoop -> fetchIO >>= \case
+        Nothing -> putMVar outChan Nothing
+        Just !result -> putMVar outChan (Just result) >> doLoop
+    activeWorkersAmountVar <- newMVar workersAmount
+    return $ (, return ()) $ A.Fetch $ fix $ \ doLoop' -> do
+      activeWorkersAmount <- takeMVar activeWorkersAmountVar
+      if activeWorkersAmount <= 0
+        then return Nothing
+        else do
+          fetchResult <- takeMVar outChan
+          case fetchResult of
+            Just result -> do
+              putMVar activeWorkersAmountVar activeWorkersAmount
+              return (Just result)
+            Nothing -> do
+              putMVar activeWorkersAmountVar (pred activeWorkersAmount)
+              doLoop'
+
+{-|
+A transform, which fetches the inputs asynchronously on the specified number of threads.
+-}
+async :: Int -> Transform input input
+async workersAmount = 
+  Transform $ \ (A.Fetch fetchIO) -> M.Acquire $ do
+    chan <- newEmptyMVar 
+    replicateM_ workersAmount $ forkIO $ fix $ \ _ -> do
+      fetchResult <- fetchIO
+      putMVar chan fetchResult
+    return (A.finiteMVar chan, return ())
diff --git a/library/Potoki/Core/Transform/FileIO.hs b/library/Potoki/Core/Transform/FileIO.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Transform/FileIO.hs
@@ -0,0 +1,30 @@
+module Potoki.Core.Transform.FileIO
+where
+
+import Potoki.Core.Prelude hiding (take, takeWhile, filter, drop)
+import Potoki.Core.Transform.Basic
+import Potoki.Core.Types
+import qualified Data.ByteString as J
+import qualified Data.Text.IO as Q
+import qualified System.Directory as I
+
+
+{-# INLINE deleteFile #-}
+deleteFile :: Transform FilePath (Either IOException ())
+deleteFile =
+  mapInIO (try . I.removeFile)
+
+{-# INLINE appendBytesToFile #-}
+appendBytesToFile :: Transform (FilePath, ByteString) (Either IOException ())
+appendBytesToFile =
+  mapInIO $ \ (path, bytes) ->
+  try $ 
+  withFile path AppendMode $ \ handleVal -> 
+  J.hPut handleVal bytes
+
+{-# INLINABLE writeTextToFile #-}
+writeTextToFile :: Transform (FilePath, Text) (Either IOException ())
+writeTextToFile =
+  mapInIO $ \ (path, text) ->
+  try $ 
+  Q.writeFile path text
diff --git a/library/Potoki/Core/Transform/Instances.hs b/library/Potoki/Core/Transform/Instances.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Transform/Instances.hs
@@ -0,0 +1,53 @@
+module Potoki.Core.Transform.Instances where
+
+import Potoki.Core.Prelude
+import Potoki.Core.Types
+import qualified Potoki.Core.Fetch as A
+
+instance Category Transform where
+  id =
+    Transform (return)
+  (.) (Transform leftVal) (Transform rightVal) =
+    Transform (leftVal <=< rightVal)
+
+instance Profunctor Transform where
+  dimap inputMapping outputMapping (Transform acquire) =
+    Transform $ \ oldFetch -> do
+      newFetch <- acquire (fmap inputMapping oldFetch)
+      return $ fmap outputMapping newFetch
+
+instance Choice Transform where
+  right' :: Transform a b -> Transform (Either c a) (Either c b)
+  right' (Transform rightTransformAcquire) =
+    Transform $ \ inFetch -> do
+      fetchedLeftMaybeRef <- liftIO $ newIORef Nothing
+      Fetch rightFetchIO <- rightTransformAcquire (A.rightHandlingLeft (writeIORef fetchedLeftMaybeRef . Just) inFetch)
+      return $ Fetch $ do
+          rightFetch <- rightFetchIO
+          case rightFetch of
+            Nothing    -> do
+              fetchedLeftMaybe <- readIORef fetchedLeftMaybeRef
+              case fetchedLeftMaybe of
+                Nothing          -> return Nothing
+                Just fetchedLeft -> do
+                  writeIORef fetchedLeftMaybeRef Nothing
+                  return $ Just (Left fetchedLeft)
+            Just element -> return $ Just (Right element)
+
+instance Strong Transform where
+  first' (Transform firstTransformAcquire) =
+    Transform $ \ inFetch -> do
+      cacheRef <- liftIO $ newIORef undefined
+      outFetch <- firstTransformAcquire (A.firstCachingSecond cacheRef inFetch)
+      return $ A.bothFetchingFirst cacheRef outFetch
+
+instance Arrow Transform where
+  arr fn =
+    Transform (return . fmap fn)
+  first =
+    first'
+
+instance ArrowChoice Transform where
+  left =
+    left'
+
diff --git a/library/Potoki/Core/Transform/State.hs b/library/Potoki/Core/Transform/State.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Transform/State.hs
@@ -0,0 +1,40 @@
+module Potoki.Core.Transform.State
+where
+
+import Potoki.Core.Prelude
+import Potoki.Core.Types
+import Potoki.Core.Transform.Instances ()
+import qualified Potoki.Core.Fetch as A
+import qualified Control.Monad.Trans.State.Strict as O
+import qualified Acquire.Acquire as M
+
+
+{-|
+Notice that you can control the emission of output of each step
+by producing a list of outputs and then composing the transform with
+the "list" transform.
+-}
+{-# INLINE runState #-}
+runState :: (a -> O.State s b) -> s -> Transform a (s, b)
+runState stateFn initialState =
+  Transform $ \ (A.Fetch fetchIO) -> M.Acquire $ do
+    stateRef <- newIORef initialState
+    return $ (, return ()) $ A.Fetch $  
+      fetchIO >>= \case
+        Just input -> do
+          currentState <- readIORef stateRef
+          case O.runState (stateFn input) currentState of
+            (output, newState) -> do
+              writeIORef stateRef newState
+              return (Just (newState, output))
+        Nothing -> return Nothing
+
+{-# INLINE evalState #-}
+evalState :: (a -> O.State s b) -> s -> Transform a b
+evalState stateFn initialState =
+  runState stateFn initialState >>> arr snd
+
+{-# INLINE execState #-}
+execState :: (a -> O.State s b) -> s -> Transform a s
+execState stateFn initialState =
+  runState stateFn initialState >>> arr fst
diff --git a/library/Potoki/Core/Transform/Types.hs b/library/Potoki/Core/Transform/Types.hs
deleted file mode 100644
--- a/library/Potoki/Core/Transform/Types.hs
+++ /dev/null
@@ -1,9 +0,0 @@
-module Potoki.Core.Transform.Types
-where
-
-import Potoki.Core.Prelude
-import qualified Potoki.Core.Fetch as A
-
-
-newtype Transform input output =
-  Transform (A.Fetch input -> IO (A.Fetch output))
diff --git a/library/Potoki/Core/Types.hs b/library/Potoki/Core/Types.hs
new file mode 100644
--- /dev/null
+++ b/library/Potoki/Core/Types.hs
@@ -0,0 +1,34 @@
+module Potoki.Core.Types
+where
+
+import Potoki.Core.Prelude
+
+
+{-|
+Passive producer of elements.
+-}
+newtype Fetch element =
+  Fetch (IO (Maybe element))
+
+{-|
+Passive producer of elements with support for early termination
+and resource management.
+-}
+newtype Produce element =
+  Produce (Acquire (Fetch element))
+
+{-|
+Active consumer of input into output.
+Sort of like a reducer in Map/Reduce.
+
+Automates the management of resources.
+-}
+newtype Consume input output =
+  {-|
+  An action, which executes the provided fetch in IO,
+  while managing the resources behind the scenes.
+  -}
+  Consume (Fetch input -> IO output)
+
+newtype Transform input output =
+  Transform (Fetch input -> Acquire (Fetch output))
diff --git a/potoki-core.cabal b/potoki-core.cabal
--- a/potoki-core.cabal
+++ b/potoki-core.cabal
@@ -1,7 +1,7 @@
 name:
   potoki-core
 version:
-  1.5.3
+  2
 synopsis:
   Low-level components of "potoki"
 description:
@@ -49,15 +49,33 @@
     Potoki.Core.IO
     Potoki.Core.Transform
   other-modules:
-    Potoki.Core.Transform.Types
+    Potoki.Core.Types
     Potoki.Core.Prelude
+    Potoki.Core.Transform.Attoparsec
+    Potoki.Core.Transform.Basic
+    Potoki.Core.Transform.ByteString
+    Potoki.Core.Transform.Concurrency
+    Potoki.Core.Transform.FileIO
+    Potoki.Core.Transform.State
+    Potoki.Core.Transform.Instances
+    Potoki.Core.IO.Fetch
   build-depends:
-    -- 
-    stm >=2.4 && <3,
-    bytestring >=0.10 && <0.11,
-    -- 
+    acquire >=0.2 && <0.3,
+    base >=4.7 && <5,
     profunctors >=5.2 && <6,
-    base >=4.7 && <5
+    stm >=2.4 && <3,
+    attoparsec >=0.13 && <0.15,
+    base-prelude <2,
+    bytestring ==0.10.*,
+    directory >=1.3 && <2,
+    foldl >=1.3 && <2,
+    hashable >=1 && <2,
+    ptr >=0.16.2 && <0.17,
+    text >=1 && <2,
+    transformers >=0.5 && <0.6,
+    unagi-chan >=0.4 && <0.5,
+    unordered-containers >=0.2 && <0.3,
+    vector >=0.12 && <0.13
 
 test-suite tests
   type:
@@ -74,10 +92,12 @@
     -- 
     potoki-core,
     -- testing:
+    attoparsec,
     tasty >=0.12 && <0.13,
     tasty-quickcheck >=0.9 && <0.10,
-    tasty-hunit >=0.9 && <0.11,
+    tasty-hunit >=0.9 && <0.10,
     quickcheck-instances >=0.3.11 && <0.4,
     QuickCheck >=2.8.1 && <3,
+    random >=1.1 && <2,
     --
     rerebase >=1.1 && <2
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -11,7 +11,10 @@
 import qualified Potoki.Core.Consume as D
 import qualified Potoki.Core.Transform as A
 import qualified Potoki.Core.Produce as E
+import qualified Data.Attoparsec.ByteString.Char8 as B
+import qualified Data.ByteString as F
 import qualified Data.Vector as G
+import qualified System.Random as H
 
 
 main =
@@ -24,6 +27,8 @@
     testProperty "consecutive consumers" $ \ (list :: [Int], amount) ->
     list === unsafePerformIO (C.produceAndConsume (E.list list) ((++) <$> D.transform (A.take amount) D.list <*> D.list))
     ,
+    potoki
+    ,
     transform
   ]
 
@@ -38,13 +43,35 @@
   ]
 
 transformProduce =
-  testCase "Produce" $ do
-    let list = [1, 2, 3] :: [Int]
-    result <- C.produceAndTransformAndConsume
-      (E.list list)
-      (A.produce (E.list . \ n -> flip replicate n n))
-      (D.list)
-    assertEqual "" [1, 2, 2, 3, 3, 3] result
+  testGroup "Produce" $ 
+  [
+    testCase "1" $ do
+      let
+        list = [1, 2, 3] :: [Int]
+      result <- C.produceAndTransformAndConsume
+        (E.list list)
+        (A.produce (E.list . \ n -> flip replicate n n))
+        (D.list)
+      assertEqual "" [1, 2, 2, 3, 3, 3] result
+  ,
+    testCase "2" $ do
+      let
+        list = [1, 2, 3] :: [Int]
+      result <- C.produceAndTransformAndConsume
+        (E.list list)
+        (A.produce (E.list . \ n -> [(n, n)]))
+        (D.list)
+      assertEqual "" [(1, 1), (2, 2), (3, 3)] result
+  ,
+    testCase "3" $ do
+      let
+        list = [1, 2, 3] :: [Int]
+      result <- C.produceAndTransformAndConsume
+        (E.list list)
+        (A.produce (E.list . \ n -> [n, n]))
+        (D.list)
+      assertEqual "" [1, 1, 2, 2, 3, 3] result
+  ]
 
 transformChoice =
   testGroup "Choice" $
@@ -59,16 +86,16 @@
     testCase "2" $ do
       let
         list = [Left 1, Left 2, Right 'z', Right 'a', Right 'b', Left 0, Right 'x', Left 4, Left 3]
-        transform = right (A.consume D.list)
+        transform = right' (A.consume D.list)
       result <- C.produceAndTransformAndConsume (E.list list) transform D.list
       assertEqual "" [Left 1, Left 2, Right "zab", Left 0, Right "x", Left 4, Left 3] result
     ,
     testCase "3" $ do
       let
-        list = [Right 'z', Right 'a', Left 3, Right 'b', Left 0, Left 1, Right 'x', Left 4, Left 3]
-        transform = left (A.consume D.list)
+        list = [Left 4, Right 'z', Right 'a', Left 3, Right 'b', Left 0, Left 1, Right 'x', Left 4, Left 3]
+        transform = left' (A.consume D.list)
       result <- C.produceAndTransformAndConsume (E.list list) transform D.list
-      assertEqual "" [Right 'z', Right 'a', Left [3], Right 'b', Left [0, 1], Right 'x', Left [4, 3]] result
+      assertEqual "" [Left [4], Right 'z', Right 'a', Left [3], Right 'b', Left [0, 1], Right 'x', Left [4, 3]] result
   ]
 
 transformArrowLaws =
@@ -164,3 +191,124 @@
       where
         transform transform =
           unsafePerformIO (C.produceAndTransformAndConsume (E.list list) transform D.list)
+
+potoki :: TestTree
+potoki =
+  testGroup "All tests for potoki's end-users functions" $
+  [
+    testCase "vector to list" $ do
+      result <- C.produceAndConsume (E.vector (G.fromList [1,2,3])) (D.list)
+      assertEqual "" [1,2,3] result
+    ,
+    testCase "just" $ do
+      result <- C.produceAndConsume (E.list [Just 1, Nothing, Just 2]) (D.transform A.just D.list)
+      assertEqual "" [1,2] result
+    ,
+    testCase "transform,consume,take" $ do
+      let
+        transform = A.consume (D.transform (A.take 3) D.list)
+        consume = D.transform transform D.list
+        produceAndConsume list = C.produceAndConsume (E.list list) (consume)
+      assertEqual "" [[1,2,3], [4,5,6], [7,8]] =<< produceAndConsume [1,2,3,4,5,6,7,8]
+      assertEqual "" [[1,2,3], [4,5,6], [7,8,9]] =<< produceAndConsume [1,2,3,4,5,6,7,8,9]
+      assertEqual "" [] =<< produceAndConsume ([] :: [Int])
+    ,
+    testCase "File reading" $ do
+      let produce =
+            E.transform (arr (either (const Nothing) Just) >>> A.just) $
+            E.fileBytes "samples/1"
+      result <- C.produceAndConsume produce (fmap F.length D.concat)
+      assertEqual "" 17400 result
+    ,
+    transformPotoki
+    ,
+    parsingPotoki
+  ]
+
+
+transformPotoki :: TestTree
+transformPotoki =
+  testGroup "Transform" $
+  [
+    testCase "Order" $ do
+      let
+        list = [Left 1, Left 2, Right 'z', Left 2, Right 'a', Left 1, Right 'b', Left 0, Right 'x', Left 4, Left 3]
+        transform = left (A.consume (D.transform (A.take 2) D.sum))
+      result <- C.produceAndConsume (E.list list) (D.transform transform D.list)
+      assertEqual "" [Left 3, Right 'z', Left 2, Right 'a', Left 1, Right 'b', Left 0, Right 'x', Left 7] result
+    ,
+    testCase "Interrupted order" $ do
+      let
+        list = [Left 1, Left 2, Right 'a']
+        transform = left (A.consume (D.transform (A.take 3) D.sum))
+      result <- C.produceAndConsume (E.list list) (D.transform transform D.list)
+      assertEqual "" [Left 3, Right 'a'] result
+    ,
+    testCase "Distinct" $ do
+      let
+        list = [1,2,3,2,3,2,1,4,1] :: [Int]
+      result <- C.produceAndConsume (E.list list) (D.transform A.distinct D.list)
+      assertEqual "" [1,2,3,4] result
+    ,
+    testCase "Distinct By" $ do
+      let
+        list = [(1, ""),(2, ""),(3, ""),(2, ""),(3, ""),(2, ""),(1, ""),(4, ""),(1, "")] :: [(Int, String)]
+      result <- C.produceAndConsume (E.list list) (D.transform (A.distinctBy fst) D.list)
+      assertEqual "" [(1, ""),(2, ""),(3, ""),(4, "")] result
+    ,
+    testCase "Concurrently" $ do
+      let
+        list = [1..20000]
+        produce = E.list list
+        transform =
+          A.concurrently 12 $
+          arr (\ x -> H.randomRIO (0, 100) >>= threadDelay >> return x) >>>
+          A.executeIO
+        consume = D.transform transform D.list
+      result <- C.produceAndConsume produce consume
+      assertBool "Is dispersed" (list /= result)
+      assertEqual "Contains no duplicates" 0 (length result - length (nub result))
+      assertEqual "Equals the original once sorted" list (sort result)
+    ,
+    testProperty "Line" $ \ chunks ->
+    let
+      expected =
+        mconcat chunks
+      actual =
+        unsafePerformIO (C.produceAndConsume produce consume)
+        where
+          produce =
+            E.list chunks
+          consume =
+            rmap (mconcat . intersperse "\n") $
+            D.transform A.extractLines D.list
+      in expected === actual
+  ]
+  
+parsingPotoki :: TestTree
+parsingPotoki =
+  testGroup "Parsing" $
+  [
+    testCase "Sample 1" $ do
+      let parser = B.double <* B.char ','
+          transform = arr (either (const Nothing) Just) >>> A.just >>> A.parseBytes parser
+          produce = E.transform transform (E.fileBytes "samples/1")
+      result <- C.produceAndConsume produce D.count
+      assertEqual "" 4350 result
+    ,
+    testCase "Sample 1 greedy" $ do
+      let parser = B.sepBy B.double (B.char ',')
+          transform = arr (either (const Nothing) Just) >>> A.just >>> A.parseBytes parser
+          produce = E.transform transform (E.fileBytes "samples/1")
+      result <- C.produceAndConsume produce D.list
+      assertEqual "" [Right 4350] (fmap (fmap length) result)
+    ,
+    testCase "Split chunk" $
+    let
+      produce = E.list ["1", "2", "3"]
+      parser = B.anyChar
+      transform = A.parseBytes parser >>> arr (either (const Nothing) Just) >>> A.just
+      consume = D.transform transform D.count
+      in do
+        assertEqual "" 3 =<< C.produceAndConsume produce consume
+  ]
