1

通过管道教程导致玩弄一些示例:

import Pipes
import qualified Pipes.Prelude as P

f1 :: Show a => Int -> [a] -> IO ()
f1 n xs = runEffect $ (for (each xs) (lift . putStrLn . show))
            >-> P.take n
            >-> P.stdoutLn

f2 :: Show a => Int -> [a] -> IO ()
f2 n xs = runEffect $ each xs
            >-> P.map show
            >-> P.take n
            >-> P.stdoutLn

但以上产生:

>>> f1 3 [1..10]
1
2
3
4
5
6
7
8
9
10
>>> f2 3 [1..10]
1
2
3
>>>

与我的预期相反,f1 和 f2 会产生相同的结果(即 f2 的结果)。问题是:他们为什么不呢?

4

1 回答 1

4

For 的类型签名为:

for
  :: Monad m =>
     Proxy x' x b' b m a'
     -> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'

你的第二个参数for是:

(lift . putStrLn . show)

其中 is 的类型为b -> Proxy ...,但由于yield不存在,因此不会在下游产生任何东西。这意味着P.take永远P.stdoutLn不会运行。由于P.take没有收到任何值,因此它永远不会关闭管道。

如果您想打印该值for并在下游产生,您可以:

f1 :: Show a => Int -> [a] -> IO ()
f1 n xs = runEffect $ (for (each xs) 
                           (\x -> (lift . putStrLn . show) x >> yield x))
            >-> P.show
            >-> P.take n
            >-> P.stdoutLn


> f1 3 [1..10]
1
1
2
2
3
3

编辑:

以下是一些基于f1using的附加代码示例for

f3 :: Show a => Int -> [a] -> IO ()
f3 n xs = runEffect $ for (each xs >-> P.take n) (lift . putStrLn . show)  

f4 :: Show a => Int -> [a] -> IO ()
f4 n xs = runEffect $ each [1..10] >-> for (P.take n) (lift . putStrLn . show)

> f3 3 [1..10]
1
2
3
> f4 3 [1..10]
1
2
3
于 2014-08-05T15:46:11.440 回答