首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >函数(行为a) -> (a -> IO b) ->行为b.它在语义上是合理的吗?

函数(行为a) -> (a -> IO b) ->行为b.它在语义上是合理的吗?
EN

Stack Overflow用户
提问于 2014-08-14 19:37:01
回答 1查看 189关注 0票数 2

我想要将IO操作映射到行为上,但(threepenny-gui)中没有这样的函数,是否有某种方法可以使用公开的API构建它。它在语义上是合理的吗?

在我的用例中,我已经在threepenny中实现了这一点。

代码语言:javascript
复制
-- Just bind the IO action to the Latch
unsafeMapIOB :: (a → IO b) → Behavior a → Behavior b
unsafeMapIOB f (B l e) = B (Prim.bindL (Prim.Latch ∘ f) l) e

-- Wrap the IO bind
bindL :: (a -> Latch b) ->  Latch a -> Latch b
bindL f l = Latch { readL = (readL ∘ f) =<< readL l}

-- Map the IO action over both Behavior and Event
unsafeMapIOT :: (a -> IO b) -> Tidings a -> Tidings b
unsafeMapIOT f x = tidings (unsafeMapIOB f $ facts x) (unsafeMapIO f $ rumors x)

我从来没有单独使用过unsafeMapIOB,只使用过unsafeMapIOT。我认为正在发生的事情是,unsafeMapIOB只执行一次,然后用事件触发unsafeMapIO。

EN

回答 1

Stack Overflow用户

发布于 2014-08-15 06:42:29

对于理想的玻璃钢语义,行为是随时间变化的函数:Time → a-it可以随着时间的推移而不断变化。这意味着,在每个更改上调用IO操作在语义上并不合理,因为在语义中没有离散更改的概念。

这在实践中也是有意义的:取决于行为的值何时发生变化通常过于依赖于实现。例如,考虑鼠标位置:值更改的频率基于轮询的频率,这非常依赖于系统。即使实际行为不是连续的,离散的更改仍然是我们不想泄露到您的程序中的细节。(在理想情况下,也许这种行为也是连续的-也许系统会进行某种插值或平滑,以补偿硬件中的底层轮询。)

为了避免依赖于这些任意的实现细节,您必须明确说明何时对您的行为进行采样以触发IO操作。您可以通过获取另一个事件流的时间组件来实现这一点,创建一个新的事件流,其中包含同时发生的事件,但值基于行为的当前值。在反应式香蕉中,您可以使用<@操作符完成此操作。特定于我们的类型,我们得到:

代码语言:javascript
复制
(<@) :: Behavior a -> Event b -> Event a

本质上,我们将行为的值映射到事件流上,从而得到一个新的事件流。然后,我们就可以使用一个标准函数在每个事件上触发一个IO操作。

最后一个问题是,你从哪里得到你的事件流,这将取决于你的特定程序。如果行为因某些特定的用户操作而发生更改,则可以获取该操作的流。您也可以只创建一个计时器事件,并在给定的时间间隔轮询。或者,您甚至可以使用union同时做这两件事!这是一个很好的例子,说明了FRP是如何非常可组合的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25307118

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档