这是一个不使用PB.break
但仅使用基本管道操作的解决方案。问题之一是数据以块的形式出现,您必须跟踪最后一个块是否以选项卡结尾:
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverloadedStrings #-}
module Lib5
where
import Pipes
import Pipes.ByteString
import qualified Data.ByteString.Char8 as BS
import Control.Monad
printAll = forever $ do a <- await; lift $ putStrLn $ "got: " ++ show a
endsWith bs ch = BS.length bs > 0 && BS.last bs == ch
convertDoubleTabs = await >>= go0
-- no precediing tab
go0 b = do
let (pre,post) = BS.breakSubstring "\t\t" b
yield pre
if BS.length post == 0
then if endsWith pre '\t'
then await >>= go1
else await >>= go0
else do yield "\t"
go0 (BS.drop 2 post)
-- last chunk ended in a tab
go1 b = do
if BS.length b == 0
then await >>= go1
else if BS.index b 0 == '\t'
then go0 (BS.drop 1 b)
else go0 b
example1 = runEffect $ each [ "this", "is\t an", "\t\texample\t", "\t."]
>-> convertDoubleTabs
>-> printAll
如果我找到使用Pipes.ByteString
and 镜头的解决方案,我会添加到这个答案中。
要转换所有连续的制表符:
convertTabs = await >>= go0
where
go0 b = do
let (pre,post) = BS.break (== '\t') b
yield pre
if BS.length post == 0
then await >>= go0
else do yield "\t"
go1 post
go1 b = do
let b' = BS.dropWhile (== '\t') b
if BS.null b'
then await >>= go1
else go0 b'
example2 = runEffect $ each [ "___\t___\t\t___\t\t\t___" ]
>-> convertTabs
>-> printAll