Functional programming 在Elm 0.15中如何保持行为?

Functional programming 在Elm 0.15中如何保持行为?,functional-programming,frp,elm,Functional Programming,Frp,Elm,删除早期版本Elm中的功能时,保持。我已经从0.14移植了一个Elm应用程序,但我一直在尝试让它的一部分工作,它使用keepWhen 所以基本上我在寻找一个函数,比如 keepWhen : Signal Bool -> a -> Signal a -> Signal a 我找到了 filter : (a -> Bool) -> a -> Signal a -> Signal a 但这不完全是一回事,我还没有弄明白如何让它工作。我在Elm 0.15中重

删除早期版本Elm中的功能时,
保持。我已经从0.14移植了一个Elm应用程序,但我一直在尝试让它的一部分工作,它使用
keepWhen

所以基本上我在寻找一个函数,比如

keepWhen : Signal Bool -> a -> Signal a -> Signal a
我找到了

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

但这不完全是一回事,我还没有弄明白如何让它工作。

我在Elm 0.15中重新实现了
keepWhen
中的
信号过滤器。这取决于观察到的
Signal.filter
使用信号值来决定是删除还是保留信号值,以及您可以组合两个信号以获得新信号(
Signal.map2(,)

如果你将你所拥有的
信号布尔
与你最终想要的
信号a
结合起来,你将得到一个
信号(a,布尔)
,你可以在
信号中进行过滤
,只需提取
布尔
值就可以决定是否保留该值

函数如下所示:

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
信号配对,以获得
信号(a,Bool)
。然后它根据信号中的
Bool
对信号进行过滤,最后去掉
Bool
,只保留“真实”值

您可以看到它在这里工作:。如果鼠标靠近(0,0)角,它将不会更新,但当鼠标移到右下角时,它将再次开始更新信号。

回答:从实用程序包导入它 最简单的方法是从软件包中使用。
(完全披露:我是作者)

重要的实施细节 请注意,实现并不是完全微不足道的。这是包中的实现(导入的
信号
模块不合格):

与中版本的重要区别在于
sampleOn
,它可以防止
的输出在布尔输入更改时更新。这两个过滤器之间的区别在于
keepWhen
from 0.14实际上只过滤
a
输入中的更新事件,并且在布尔输入变为
True
时不对其进行采样

另一个实现也是名为signalextra的

图表 如果你对大理石图略知一二,也许会有所帮助。我将在下面发布相关内容的截图

您阅读这些图表的方式:

  • 时间从左向右流动
  • 线路是一种信号
  • 块是一个函数,它接收上面的两个信号并生成下面的信号
  • 每行左侧的形状是初始值
  • 填充形状是信号上的事件
  • 轮廓形状适用于信号不变的情况
  • 我用形状来表示类型
  • 我用颜色来代表不同的价值观


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

    非常优雅!我听说0.12版本之前的keepWhen和“现代”版本之间存在差异,但直到你现在非常清楚地解释了这一差异,我才理解这一差异。非常感谢!
    keepWhen : Signal Bool -> a -> Signal a -> Signal a
    keepWhen boolSig a aSig =
      zip boolSig aSig
      |> sampleOn aSig
      |> keepIf fst (True, a)
      |> map snd