我正在使用管道库,需要String使用ASCII编码将ByteString流转换为线流(即).我知道还有其他库(Pipes.Text和Pipes.Prelude)可能让我更容易从文本文件中产生行,但由于其他一些代码,我需要能够String从Producer中获取行ByteString.
更正式地说,我需要将a转换Producer ByteString IO ()为a Producer String IO (),从而产生线条.
我相信,这一定是一个班轮对于有经验的管道,程序员,但我至今没能成功地通过所有的黑客FreeT,并Lens在管道-字节串-trickery.
任何帮助深表感谢!
斯蒂芬
如果你需要那种类型的签名,那么我会建议:
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
Run Code Online (Sandbox Code Playgroud)
这是因为类型purely folds mconcat是:
purely folds mconcat
:: (Monad m, Monoid t) => FreeT (Producer t m) r -> Producer t m r
Run Code Online (Sandbox Code Playgroud)
...... t在这种情况下将是Text:
purely folds mconcat
:: Monad m => FreeT (Producer Text m) r -> Producer Text m r
Run Code Online (Sandbox Code Playgroud)
任何时候您想要减少您可能想要使用Producer的定FreeT界流的每个子组purely folds.然后,这只是选择Fold减少子组的权利.在这种情况下,您只想连接Text组中的所有块,以便传入mconcat.我一般不建议这样做,因为它会在很长的行上断开,但是你指定你需要这种行为.
这是冗长的原因是因为pipes生态系统促进Text了过度String,并试图鼓励处理任意长线.如果您不受其他代码的约束,那么更惯用的方法就是:
view (utf8 . lines)
Run Code Online (Sandbox Code Playgroud)