如何在Elm 0.15中保持行为?

时间:2015-04-25 21:22:14

标签: functional-programming frp elm

删除了早期版本的Elm中的keepWhen函数。我已经从0.14移植了一个Elm应用程序,但是我一直试图让它的一部分工作,它正在使用keepWhen

所以基本上我正在寻找像

这样的功能
keepWhen : Signal Bool -> a -> Signal a -> Signal a

我找到了

filter : (a -> Bool) -> a -> Signal a -> Signal a

但这不是一回事,我还没弄明白如何让它发挥作用。

2 个答案:

答案 0 :(得分:4)

答案:从实用程序包中导入

最简单的方法是使用Signal.Extra.keepWhen包中的signal-extra (完全披露:我是作者)

重要的实施细节

请注意,实施并非完全无关紧要。这是包中的实现(some text1 some text2 <img src="2.jpg>" 模块导入不合格):

Signal

kqr's answer中版本的重要区别在于keepWhen : Signal Bool -> a -> Signal a -> Signal a keepWhen boolSig a aSig = zip boolSig aSig |> sampleOn aSig |> keepIf fst (True, a) |> map snd ,当布尔输入发生变化时,它会使sampleOn的输出不会更新。两个过滤器之间的区别在于,来自0.14的keepWhen实际上仅过滤来自keepWhen输入的更新事件,并且在布尔输入变为a时不对其进行采样。

另一个实现也是名为sampleWhen的信号额外实现。

图表

如果你对大理石图有所了解,那么these old diagrams可能有所帮助。我将在下面发布相关内容的屏幕截图。

您阅读这些图表的方式:

  1. 时间从左向右流动。
  2. 一条线是一个信号。
  3. 该块是一个函数,它接收上面的两个信号并产生下面的信号。
  4. 每行左侧的形状为初始值。
  5. 填充的形状是信号上的事件。
  6. 轮廓形状适用于信号未发生变化的情况。
  7. 我用形状来表示类型。
  8. 我用颜色来表示不同的值。
  9. keepWhen and older keepWhen+sample marble diagrams

    请注意,标记为旧行为的第二个图表与kqr的答案中的代码行为相匹配。

答案 1 :(得分:2)

我已经按照{0}中的keepWhen重新实现了Signal.filter。这取决于观察Signal.filter使用信号的值来决定是否丢弃或保持信号值,以及您可以组合两个信号以获得新信号(Signal.map2 (,))的事实。

如果您将Signal Bool与最终想要的Signal a合并,那么您可以在Signal (a, Bool)中获取Signal.filter,只需提取Bool值决定是否要保留该值。

该功能如下所示:

keepWhen : Signal Bool -> a -> Signal a -> Signal a
keepWhen cond def val =
  let combined = Signal.map2 (,) val cond
      filtered = Signal.filter snd (def, False) combined
      final    = Signal.map fst filtered
  in  final

首先将“值”信号与Bool信号配对以获得Signal (a, Bool)。然后它根据其中的Bool过滤该信号,最后剥离Bool并仅保留“真实”值。

你可以在这里看到它:http://share-elm.com/sprout/553c01afe4b06aacf0e8985a。如果您将鼠标靠近(0,0)角,它将不会更新,但当您将鼠标移动到更右侧时,它将再次开始更新信号。