gpt4 book ai didi

haskell - react 香蕉可以处理网络中的循环吗?

转载 作者:行者123 更新时间:2023-12-03 20:42:57 25 4
gpt4 key购买 nike

我们有这样的代码:

 guiState :: Discrete GuiState
guiState = stepperD (GuiState []) $
union (mkGuiState <$> changes model) evtAutoLayout

evtAutoLayout :: Event GuiState
evtAutoLayout = fmap fromJust . filterE isJust . fmap autoLayout $ changes guiState

您可以看到 evtAutoLayout 馈入 guiState 馈入
evtAutoLayout——所以那里有一个循环。这是故意的。汽车
layout 调整 gui 状态直到达到平衡,然后
它返回 Nothing ,所以它应该停止循环。新的模型变化
当然,可以再次启动它。

但是,当我们将这些放在一起时,我们会在
编译函数调用。即使 autoLayout = Nothing,它仍然会在编译期间导致堆栈溢出。

如果我删除 guiState 中的联合调用并删除 evtAutoLayout
图片...
 guiState :: Discrete GuiState
guiState = stepperD (GuiState []) $ mkGuiState <$> changes model

它工作正常。

有什么建议么?

最佳答案

问题

Does the reactive-banana library support recursively defined events?



答案不止一个,而是三个。简短的回答是:1. 一般不会,2. 有时会,3. 有解决方法是。

这里是长答案。
  • react 香蕉的语义不支持定义 Event直接就自身而言。

    这是 Conal Elliott 在其原始 FRP 语义中做出的决定,我决定坚持下去。它的主要好处是语义仍然非常简单,你总是可以从以下方面思考
    type Behavior a = Time -> a
    type Event a = [(Time,a)]

    我提供了一个模块Reactive.Banana.Model几乎完全实现了这个模型,你可以引用它的源代码来解决任何关于 react 香蕉语义的问题。特别是,您可以使用它来推理您的示例:使用笔和纸进行计算或在 GHCi 中尝试(使用一些模拟数据)将告诉您值 evtAutoLayout等于 _|_ ,即未定义。

    后者可能令人惊讶,但正如您所写,该示例确实是未定义的:GUI 状态仅在 evtAutoLayout 时才会更改。事件发生,但只有在您知道 GUI 状态是否发生变化时才会发生,这反过来等。您总是需要通过插入一个小的延迟来打破扼杀的反馈循环。不幸的是,reactive-banana 目前不提供插入小延迟的方法,主要是因为我不知道如何用 [(Time,a)] 来描述小延迟。以允许递归的方式建模。 (但请参阅答案 3。)
  • 可以并鼓励定义 Event根据 Behavior再次引用事件。换句话说,只要你通过一个行为,就允许递归。

    一个简单的例子是
    import Reactive.Banana.Model

    filterRising :: (FRP f, Ord a) => Event f a -> Event f a
    filterRising eInput = eOutput
    where
    eOutput = filterApply (greater <$> behavior) eInput
    behavior = stepper Nothing (Just <$> eOutput)

    greater Nothing _ = True
    greater (Just x) y = x < y

    example :: [(Time,Int)]
    example = interpretTime filterRising $ zip [1..] [2,1,5,4,8,9,7]
    -- example = [(1.0, 2),(3.0, 5),(5.0, 8),(6.0, 9)]

    给定一个事件流,函数 filterRising仅返回大于先前返回的那些事件。这在 documentation for the stepper function 中有所暗示.

    但是,这可能不是您想要的那种递归。
  • 尽管如此,还是可以在 react 香蕉中插入小的延迟,它只是不是核心库的一部分,因此没有任何保证的语义。此外,您确实需要事件循环的一些支持才能做到这一点。

    例如,您可以使用 wxTimer 来安排事件在您处理完当前事件后立即发生。 Wave.hs示例演示了 wxTimer 与 reactive-banana 的递归使用。我不太清楚将计时器间隔设置为 0 时会发生什么,但是,它可能执行得太早。您可能需要进行一些试验才能找到一个好的解决方案。

  • 希望有帮助;随时要求澄清,示例等。

    披露:我是响应式香蕉库的作者。

    关于haskell - react 香蕉可以处理网络中的循环吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7850389/

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