从列表创建信号

Create a Signal from a List

是否可以从 List 创建一个 Signal?基本上我想要的是带有签名 List a -> Signal a 的东西。我知道 Signal 代表一个随时间变化的值,所以像这样的东西实际上没有任何意义(即我想不出在生产代码中使用它的理由)。

虽然我可以看到它的测试应用程序。例如,假设某个函数依赖于 Signal 的过去值(例如通过 foldp),并且您想在信号接收到值 x、y 的情况下对系统状态做出断言, 和 z.

请注意,Signal 没有任何特殊之处,表示它只会接收固定数量的值。我更像是在想它:在生产中你有 Signal 次鼠标点击,你想从给定的起始位置测试它,在给定的一组点击之后,系统应该在其他一些已知的状态。我知道您可以通过调用该函数固定次数并使用新值反馈结果来模拟这一点,我只是想知道这是否可能。

我想这是可能的。您使用基于时间的信号,并将列表中的值映射到它上面:

import Time
import Graphics.Element exposing (show)

list = [1..10]


signalFromList : List a -> Signal a
signalFromList list =
  let
    (Just h) =
      List.head list

    time =
      Time.every Time.second

    maybeFlatMap =
      flip Maybe.andThen

    lists =
      Signal.foldp (always <| maybeFlatMap List.tail) (Just list) time
  in
    Signal.filterMap (maybeFlatMap List.head) h lists

main = Signal.map show <| signalFromList list

但是!

没有信号做测试应该不难。如果你在某处有一个 foldp,在测试中你可以在列表 [x,y,z] 上使用 List.foldl。这应该使您能够在输入 xyz 后查看程序的状态。

我不认为有任何方法可以在纯榆树中同步完成(Apanatshka 的回答很好地说明了如何跨时间设置事件序列为什么这是个坏主意)。如果我们看看大多数信号是如何定义的,我们会发现它们在某个时候都进入了一个本地包。

然后问题就变成了:我们可以本地做到这一点吗?

f : List a -> Signal a

我经常把(信号a)想成'an a that changes over time'。这里我们提供了一个as的List,想让函数帮我们让它随时间变化。

在我们继续之前,我建议快速浏览一下 Native/Signal.js:https://github.com/elm-lang/core/blob/master/src/Native/Signal.js

假设我们带着我们的 List of as 回到家乡。我们想要有点像 Signal.constant 的东西,但有一些额外的行为 'sends' 之后的每个行为。不过,我们什么时候可以发送?我猜我们不能在信号构造函数中这样做,因为我们仍在构建信号图。这给我们留下了几个其他选择:

  • 关于 setTimeout 的令人发指的事情,安排在未来适当的时间发送每个 'a'
  • 在 elm 中设计一个钩子 运行time 以便我们可以 运行 在信号图完全构建时的任意回调

至少对我来说,前者听起来容易出错,我希望后者不存在(而且永远不存在)!

为了测试,我会采用您建议的使用 List fold 来模仿 foldp 行为的方法。