【问题标题】:How to know what made a behavior change?如何知道是什么导致了行为改变?
【发布时间】:2015-07-02 03:53:56
【问题描述】:

我正在为列表框逻辑编写网络描述。
这真的很简单:我对 (Maybe) 当前选定的项目有一个行为,我想要它,以便每当用户向列表中添加新项目时,当前选定的项目将选择刚刚创建的值。

用户也可能从列表中删除项目,并导致各种其他更改,所以我必须知道何时创建新项目;我不能在每次更改时只选择最后一项。

我真的没有任何代码可以显示它,因为我对要做什么的所有猜测甚至都不能用 API* 编写,但我有 Frameworks t 和(简化)的上下文:

bDb :: Behavior t [Entry] -- Created with accumB.
bSelected :: Behavior t (Maybe Entry) -- Created with accumB.
eAddEntry :: Event t () -- User clicked an add button. Created with fromAddHandler.

* 好吧,我确实考虑过使用eAddEntry 来选择最后一个条目,但这太糟糕了,即使它可以工作,也只是添加新项目和选择它之间的竞赛。

我该怎么办?

【问题讨论】:

  • 您能否简单地将您的[Entry] 与其accumB 中的其他内容相乘,以告诉您最后更改的来源?所以你会得到带有一些适当数据类型data ReasonItChanged = UserAdded | UserRemoved([Entry], ReasonItChanged)
  • @Cactus Err.. 好吧,我真的很想避免增加这种复杂性,但如果 FRP/reactive-banana 没有更好的方法,我会求助。不过我会试试的。非常感谢。
  • 你看过CRUD.hs这个例子吗?它处理类似的情况。这个想法是当前选定的项目来自两个来源:用户在列表框中单击,以及从程序内部进行更改。最简单的方法是将后者视为“建议”,而将前者视为“确定性”。

标签: haskell frp reactive-banana


【解决方案1】:

我在 cmets 中尝试了 Cactus 的建议,结果证明它无法完成(我必须在 let 块的中间绑定选择行为和列表行为是,但它们相互依赖)。

所以我决定从头开始,但这次做得过头了,并将整个状态包装在它自己的数据类型中,网络只会驱动它。所以网络真正要做的就是根据事件调用网络上的函数,仅此而已。结果证明它比 imo 好得多,因为没有应用式的混乱,所有的功能实际上只是简单的功能,而且它更加模块化(例如,我可以决定根本不使用 FRP,并且更改将非常小 - - 只需使用函数切换触发;虽然我仍然需要找到放置状态的位置,这可能是不纯的东西,例如 IORef)。

太干净了,看起来有点像这样:

data DbState = DbState Database SelectedItem LastAction Etc Etc
emptyState :: DbState
stateRemove, stateAdd :: DbState -> DbState

行为只是:

let bDb = accumB emptyState $ unions
      [stateAdd <$ eAddEntry
      ,stateRemove <$ eRemoveEntry
      ]

之前,我的长度线充满了 lambda、&lt;$&gt;&lt;*&gt; 等。

现在我只是 rectimate' 并通过 LastAction 看到变化。
我还像这样非常简单地添加了错误检查。

【讨论】:

    猜你喜欢
    • 2020-12-13
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多