IO 运行 应该在传播期间内联吗?
Should IO run inline during propagation?
我正在尝试在 Idris 中编写 FRP 库。此库设计为 运行 在单线程环境中。未来实施 Monad
和 Align
。我想用这些简化的类型签名实现功能:
createFutureResolveLater : (Future a, a -> IO ()) -- later time
createFutureResolveNow : a -> IO (Future a) -- current time
pure : a -> Future a -- before everything
align : Future a -> Future a -> Future (These a b) -- min of two times
join : Future (Future a)) -> Future a -- max of two times
exeEvent : Future (IO a) -> IO (Future a) -- ??
simultaneous : Future a -> Future b -> Future Bool -- min of two times
subFuture : Future a -> (a -> IO ()) -> IO ()
在我看来很明显
simultaneous a a, simultaneous a (fmap f a), etc.
应该是解析为 true 的未来。
在
do
oe <- exeEvent ie
let s = simultaneous oe ie
...
应该解析为真吗?
在 reactive-banana 中,s 为假。请参阅 http://hackage.haskell.org/package/reactive-banana-1.2.1.0/docs/Reactive-Banana-Frameworks.html
中的 mapEventIO
在反射中,s 也很可能是假的。请参阅 https://daig.github.io/reflex/Reflex-PerformEvent-Class.html
中的 performEvent
为什么这些库作者选择 s 为假?
正在尝试弄清楚你在问什么。我想您想知道如何解释 IO
需要时间的操作,不是吗?因为如果 IO
动作是瞬时的,这就不是问题了。尽管对我来说还有一个问题,即 IO
操作会阻塞直到未来发生还是异步安排它?
如果这是一个 non-blocking 调用,我会说它应该等到 IO
操作完成。 (我也会称它为 schedFuture
或类似的名称,以表明它不会阻塞。)否则你可能会遇到 Future
的情况,但它的价值仍然存在不可用,这可能会搞砸合并事件等功能的逻辑
如果这是一个阻塞调用,我会改为提供
waitFuture :: Future a -> IO a
并让用户处理其余部分(例如,如果他们想保留时间,他们可以 fmap (const x)
在原来的未来,他们可以在操作完成时使用 now :: IO (Future ())
如果他们想要它, ETC。)。如果你能为他们想出好的名字,那么为他们提供组合器可能是值得的,否则他们很容易,我只是平底船。
我还发现在制作这样的系统时区分 "morally instantaneous" IO
操作和可能阻塞的操作很有帮助。我想这与 javascript 对异步和常规堆栈调用的区别是平行的。像这样模糊的问题很多,对应的显而易见的答案往往取决于这个区分。
我正在尝试在 Idris 中编写 FRP 库。此库设计为 运行 在单线程环境中。未来实施 Monad
和 Align
。我想用这些简化的类型签名实现功能:
createFutureResolveLater : (Future a, a -> IO ()) -- later time
createFutureResolveNow : a -> IO (Future a) -- current time
pure : a -> Future a -- before everything
align : Future a -> Future a -> Future (These a b) -- min of two times
join : Future (Future a)) -> Future a -- max of two times
exeEvent : Future (IO a) -> IO (Future a) -- ??
simultaneous : Future a -> Future b -> Future Bool -- min of two times
subFuture : Future a -> (a -> IO ()) -> IO ()
在我看来很明显
simultaneous a a, simultaneous a (fmap f a), etc.
应该是解析为 true 的未来。
在
do
oe <- exeEvent ie
let s = simultaneous oe ie
...
应该解析为真吗?
在 reactive-banana 中,s 为假。请参阅 http://hackage.haskell.org/package/reactive-banana-1.2.1.0/docs/Reactive-Banana-Frameworks.html
中的 mapEventIO在反射中,s 也很可能是假的。请参阅 https://daig.github.io/reflex/Reflex-PerformEvent-Class.html
中的 performEvent为什么这些库作者选择 s 为假?
正在尝试弄清楚你在问什么。我想您想知道如何解释 IO
需要时间的操作,不是吗?因为如果 IO
动作是瞬时的,这就不是问题了。尽管对我来说还有一个问题,即 IO
操作会阻塞直到未来发生还是异步安排它?
如果这是一个 non-blocking 调用,我会说它应该等到 IO
操作完成。 (我也会称它为 schedFuture
或类似的名称,以表明它不会阻塞。)否则你可能会遇到 Future
的情况,但它的价值仍然存在不可用,这可能会搞砸合并事件等功能的逻辑
如果这是一个阻塞调用,我会改为提供
waitFuture :: Future a -> IO a
并让用户处理其余部分(例如,如果他们想保留时间,他们可以 fmap (const x)
在原来的未来,他们可以在操作完成时使用 now :: IO (Future ())
如果他们想要它, ETC。)。如果你能为他们想出好的名字,那么为他们提供组合器可能是值得的,否则他们很容易,我只是平底船。
我还发现在制作这样的系统时区分 "morally instantaneous" IO
操作和可能阻塞的操作很有帮助。我想这与 javascript 对异步和常规堆栈调用的区别是平行的。像这样模糊的问题很多,对应的显而易见的答案往往取决于这个区分。