Mic*_*man 6 haskell conduit haskell-pipes
我正在尝试理解管道4.0,并希望转换一些管道代码.假设我有一个Int
s 流,我想跳过前五个,然后得到以下的总和5.使用普通列表,这将是:
sum . take 5 . drop 5
Run Code Online (Sandbox Code Playgroud)
在管道中,这将是:
drop 5
isolate 5 =$ fold (+) 0
Run Code Online (Sandbox Code Playgroud)
或者作为一个完整的程序:
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
Run Code Online (Sandbox Code Playgroud)
但是,我不太确定如何使用管道来做到这一点.
我之前没有使用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
Run Code Online (Sandbox Code Playgroud)
更新:
由于示例中没有"有效"处理,我们甚至可以使用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
Run Code Online (Sandbox Code Playgroud)
更新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"
Run Code Online (Sandbox Code Playgroud)