6

パイプ 4.0 を理解しようとしていて、いくつかのコンジット コードを変換したいと考えています。s のストリームがありInt、最初の 5 つをスキップして、次の 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

ただし、パイプでこれを行う方法はよくわかりません。

4

2 に答える 2

5

これまでパイプを使用したことはありませんでしたが、チュートリアルを実行した後、非常に簡単であることがわかりました。

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、モナドをパイプのベースモナドとして使用することもできます。

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 :

以下は私が思いついた解決策です(要旨リンクコメント用)が、もっとエレガントにできる気がします

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"
于 2013-09-24T09:02:31.860 に答える