gpt4 book ai didi

coroutine - purescript-coroutines 中的 `pullFrom` 和 `connect` 有什么区别?

转载 作者:行者123 更新时间:2023-12-03 08:06:49 24 4
gpt4 key购买 nike

我不确定我是否理解 purescript-coroutines 中有一个 connect 和一个 pullFrom 函数的原因。 ,以及何时使用它们。看看这些类型,它们似乎已经习惯了改变“通信方向”(我不确定这是否是正确的思考方式)。

pullFrom :: forall o m a. MonadRec m => Consumer o m a -> Producer o m a -> Process m a

connect :: forall o f m a. (MonadRec m, Parallel f m) => Producer o m a -> Consumer o m a -> Process m a

所以如果我有一个消费者和一个生产者......

consumer :: forall e a. (Show a) => Consumer a (Eff (console :: CONSOLE | e)) Unit
consumer = forever do
s <- await
lift (log $ show s)

numberProducer :: forall m. (Monad m) => Producer Int m Unit
numberProducer = go 0
where
go i = do emit i
go (i + 1)

对我来说,消费者可以从生产者那里获取数据是有意义的,如果我运行它,我可以看到显示的数字...

main = do
runProcess (pullFrom consumer numberProducer)

但是,如果我connect 生产者和消费者,它似乎什么也没做。我假设当您将生产者连接到消费者时,信号与 pullFrom 的方向相反,但我不确定这个想法是否正确。

main = do
runProcess (connect producer consumer)

最佳答案

好吧,这里面有一个有趣的小惊喜……不过我会在一分钟内谈到这一点。

pullFrom 的引入是为了让消费者在流程形成时“负责”- 只要消费者处于打开状态(等待输入),流程就会存在。

connect 只要生产者或消费者打开就运行,并且该过程仅在它们都完成时终止。

为了实现这一点,connect 有一个 Parallel 类约束,因为创建的进程同时依赖于消费者和生产者 - pullFrom 不需要这是因为该过程仅依赖于消费者

这就是“有趣”惊喜的来源 - 让我困惑了一分钟。 Eff 不是 Parallel...那么您的代码如何工作?这是因为它正在为 main 推断这种类型:

main :: forall t. (Parallel t (Eff (console :: CONSOLE))) => Eff (console :: CONSOLE) Unit

所以当你的程序运行时没有任何反应,因为在 JS 中,main 期望为 Parallel 约束传递一个字典,然后是 Eff 进行评估。生成的对 main 的调用只是 Main.main();,因此它从未实际评估 Eff,因为它需要是 Main.main(impossibleParallelDictionary )();.

尝试将此类型添加到您的main:

main :: Eff (console :: CONSOLE) Unit

而且您会看到它不再进行类型检查。

尽管如此,您可以使用 Aff,并且使用 Aff 时,connectpullFrom 之间的区别是无法区分的对于这个例子:

import Prelude

import Control.Coroutine (Consumer, Producer, await, connect, emit, runProcess)
import Control.Monad.Aff (Aff, launchAff)
import Control.Monad.Aff.Console (CONSOLE, log)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Exception (EXCEPTION)
import Control.Monad.Rec.Class (forever)
import Control.Monad.Trans.Class (lift)

consumer :: forall e a. (Show a) => Consumer a (Aff (console :: CONSOLE | e)) Unit
consumer = forever do
s <- await
lift (log $ show s)

numberProducer :: forall m. (Monad m) => Producer Int m Unit
numberProducer = go 0
where
go i = do emit i
go (i + 1)

main :: Eff (err :: EXCEPTION, console :: CONSOLE) Unit
main = void $ launchAff $ runProcess (connect numberProducer consumer)

如果我们稍微修改示例,我们可以看到差异的图示:

import Prelude

import Control.Coroutine (Consumer, Producer, await, emit, connect, runProcess)
import Control.Monad.Aff (Aff, launchAff, later')
import Control.Monad.Aff.Console (CONSOLE, log)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Exception (EXCEPTION)
import Control.Monad.Trans.Class (lift)

consumer :: forall e a. (Show a) => Consumer a (Aff (console :: CONSOLE | e)) Unit
consumer = do
s <- await
lift (log $ show s)

numberProducer :: forall eff. Producer Int (Aff eff) Unit
numberProducer = do
emit 0
lift $ later' 10000 $ pure unit

main :: Eff (err :: EXCEPTION, console :: CONSOLE) Unit
main = void $ launchAff $ runProcess (connect numberProducer consumer)

这样,程序将打印 0,等待 10 秒,然后退出。如果您将 connect numberProducer consumer 切换为 consumer `pullFrom` numberProducer,程序将打印 0 并立即退出。

关于coroutine - purescript-coroutines 中的 `pullFrom` 和 `connect` 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42725880/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com