簡體   English   中英

使用管道4.0折疊流的子集

[英]Folding a subset of a stream using pipes 4.0

我正在嘗試理解管道4.0,並希望轉換一些管道代碼。 假設我有一個Int流,我想跳過前五個,然后得到以下的總和5.使用普通列表,這將是:

sum . take 5 . drop 5

在管道中,這將是:

drop 5
isolate 5 =$ fold (+) 0

或者作為一個完整的程序:

import Data.Conduit
import Data.Conduit.List (drop, isolate, fold)
import Prelude hiding (drop)

main :: IO ()
main = do
    res <- mapM_ yield [1..20] $$ do
        drop 5
        isolate 5 =$ fold (+) 0
    print res

但是,我不太確定如何使用管道來做到這一點。

我之前沒有使用Pipes,但在完成教程后我發現它非常簡單:

import Pipes
import qualified Pipes.Prelude as P

nums :: Producer Int IO ()
nums = each [1..20]

process :: Producer Int IO ()
process = nums >-> (P.drop 5) >-> (P.take 5)

result :: IO Int
result = P.fold (+) 0 id process

main = result >>= print

更新:

由於示例中沒有“有效”處理,我們甚至可以使用Identity monad作為管道的基本monad:

import Pipes
import qualified Pipes.Prelude as P
import Control.Monad.Identity

nums :: Producer Int Identity ()
nums = each [1..20]

process :: Producer Int Identity ()
process = nums >-> (P.drop 5) >-> (P.take 5)

result :: Identity Int
result = P.fold (+) 0 id process

main = print $ runIdentity result

更新1

下面是我提出的解決方案(關於gist鏈接評論),但我覺得它可以變得更優雅

fun :: Pipe Int (Int, Int) Identity ()
fun = do
  replicateM_ 5 await
  a <- replicateM 5 await
  replicateM_ 5 await
  b <- replicateM 5 await
  yield (sum a, sum b)

main = f $ runIdentity $ P.head $ nums >-> fun where
  f (Just (a,b)) = print (a,b)
  f Nothing = print "Not enough data"

要回答您的評論,這仍然適用於一般情況。 我也在reddit上發布了相同的答案,你在那里也問過類似的問題,但我在這里重復答案:

import Pipes
import Pipes.Parse
import qualified Pipes.Prelude as P

main :: IO ()
main = do
    res <- (`evalStateT` (each [1..20])) $ do
        runEffect $ for (input >-> P.take 5) discard
        P.sum (input >-> P.take 5)
    print res

這將概括為您考慮的更復雜的案例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM