是否有一个预定义的函数用于管道类比`takeWhile`?

时间:2015-11-13 00:44:19

标签: haskell conduit

我发现Data.Conduit.List模块中缺少以下函数,我找不到使用该模块中的函数来组合它的简单方法。

takeWhile :: Monad m => (a -> Bool) -> Consumer a m [a]
takeWhile p = await >>= \case
                Nothing -> return []
                Just b  -> if p b
                  then (b :) <$> takeWhile p
                  else (leftover b) >> return []

此功能在我的应用程序中非常有用,我有时需要将下几个项目组合在一起,而且我不确定有多少项目。

这个函数的缺失对我来说有点奇怪,因为有take :: Monad m => Int -> Consumer a m [a]groupBy :: Monad m => (a -> a -> Bool) -> Conduit a m [a],但没有takeWhile

我错过了什么吗?

编辑:根据@ ErikR的请求,这里有两个简单的例子,可以说明我认为这个功能有用的原因。

情况1:协议指定流中有标题部分。为简单起见,我们假设它是String流,标题项由前导@标记。

流内容:

@language=English
@encoding=Unicode
Apple
Orange
Blue
Red
Sheep
Dog
...

使用takeWhile的代码:

myConduit :: Conduit String IO String ()
myConduit = do
    headers <- takeWhile ((== '@') . head)
    awaitForever $ \ item -> do
        case getLanguage headers of
            English -> ...
            French  -> ...

案例2:协议指定前缀为@的项目有几个以+为前缀的延续。

流内容:

Apple
Orange
Blue
@Has
+kell
@A
+Really
+Long
+Word
Dog
...

使用takeWhile的代码:

myConduit :: Conduit String IO String ()
myConduit = runMaybeC . forever $ do
    a <- maybe (lift mzero) return =<< await
    aConts <- if head item == '@' then takeWhile ((== '+') . head)
                                  else return []
    liftIO . putStrLn . concat $ a : aConts

然而,除了有用之外,它也是为了完整性。我看到Data.Conduit.List的目标是在Conduit上下文中提供一组“类似列表”的操作。我认为应该提供像takeWhile这样的面包和黄油功能,以及像dropWhile这样的兄弟姐妹,以便人们在将管道视为列表时不必改变他们的编码风格。 / p>

0 个答案:

没有答案