这是加布里埃尔,他发布了管道。我一直在与 Paolo 合作,我们在作品中有一个更优雅的实现,它比他最初的提议更强大和类型安全。您的问题的简短回答是最终实现是原始管道的超集,您可以编写与以前相同的代码,具有相同的行为和语义。
我什至可以在这里简单地总结一下。Await 和 yield 语句是管道可以放弃控制的唯一方式,因此如果上游或下游管道终止,我们会为每个语句附加一个回退。回退会永久降级管道,并且不能再重复失败的操作。失败的等待将管道降级到生产者,失败的产量将管道降级到消费者。如果生产者未能让出或消费者未能等待,它们将被降级为基本 monad,它不能再失败。
消费者和生产者现在是不同的类型,并且没有暴露。它们与类型管道类型相同,只是缺少 Await 或 Yield 构造函数。这是必要的,至少对于生产者类型而言,因为管道没有可以禁止等待语句的输入类型。
Await 和 yield 语句默认终止作为它们的回退行为,这与之前的行为相同。Await 和 yield 将被分类以在支持它们的降级状态下工作。但是,一旦我们提出比 tryAwait 或 tryYield 更性感的名称,您现在可以选择提供自己的后备选项。
我仍然需要验证 Pipes 是否仍会使用此扩展名构成一个类别,但这似乎很有可能。它也是 100% 类型安全的,并使用类型来强制降级,而不是布尔值,并且程序员证明是不变的。
编辑:一些能激发你胃口的功能代码(从 github 存储库中签出“try”分支以使用扩展):
printer = forever $ await >>= lift . print
take' n = replicateM_ n $ await >>= yield
fromList' = mapM_ (yieldOr (lift $ putStrLn "Undelivered elements))
diagnose = forever $ do
x <- awaitOr (lift $ putStrLn "Await failed")
yieldOr (lift $ putStrLn "Yield failed") x
> runPipe $ printer <+< take' 3 <+< diagnose <+< fromList [1..10]
1
2
3
Yield failed
Undelivered elements
> runPipe $ printer <+< take' 10 <+< diagnose <+< fromList [1..3]
1
2
3
Await failed