If you need this type signature, I would suggest the following:
import Control.Foldl (mconcat, purely) import Data.ByteString (ByteString) import Data.Text (unpack) import Lens.Family (view) import Pipes (Producer, (>->)) import Pipes.Group (folds) import qualified Pipes.Prelude as Pipes import Pipes.Text (lines) import Pipes.Text.Encoding (utf8) import Prelude hiding (lines) getLines :: Producer ByteString IO r -> Producer String IO (Producer ByteString IO r) getLines p = purely folds mconcat (view (utf8 . lines) p) >-> Pipes.map unpack
This works because the purely folds mconcat :
purely folds mconcat :: (Monad m, Monoid t) => FreeT (Producer tm) r -> Producer tmr
... where t in this case will be Text :
purely folds mconcat :: Monad m => FreeT (Producer Text m) r -> Producer Text mr
Anytime you want to reduce each Producer subgroup of a FreeT -delimited stream, you probably want to use purely folds . Then it's just a matter of choosing the right Fold to reduce the subgroup with. In this case, you just want to merge all the Text fragments within the group, so you go into mconcat . I usually do not recommend this, as it will break into very long lines, but you indicated that you need this behavior.
The reason this is verbose is because the pipes ecosystem promotes Text over String , and also tries to encourage handling of arbitrarily long strings. If you were not limited to your other code, then a more idiomatic approach would be as follows:
view (utf8 . lines)
source share