如何根据另一个信号参数化一个信号?例如,假设我想根据鼠标的 x 位置修改 fps。类型有:
Mouse.x : Signal Int
fps : number -> Signal Time
我怎样才能让 Elm 理解这个伪代码的内容:
fps (Mouse.x) : Signal Time
显然,lift
在这种情况下不起作用。我认为结果会是Signal (Signal Time)
(但我对 Elm 还是很陌生)。
谢谢!
如何根据另一个信号参数化一个信号?例如,假设我想根据鼠标的 x 位置修改 fps。类型有:
Mouse.x : Signal Int
fps : number -> Signal Time
我怎样才能让 Elm 理解这个伪代码的内容:
fps (Mouse.x) : Signal Time
显然,lift
在这种情况下不起作用。我认为结果会是Signal (Signal Time)
(但我对 Elm 还是很陌生)。
谢谢!
fps Mouse.x
导致 fps 需要的类型错误Int
,而不是Signal Int
.
lift fps Mouse.x : Signal (Signal Int)
你是对的。正如 CheatX 的回答所提到的,您不能在 Elm 中使用这些“嵌套信号”。
似乎您要的是Standard Libraries中尚不存在的东西。如果我正确理解您的问题,您想要一个时间(或 fps)信号,其时间可以动态更改。就像是:
dynamicFps : Signal Int -> Signal Time
使用内置函数 likelift
并不能让您自己从 type 的函数构造这样的函数Int -> Signal Time
。
我认为您在这里有三个选择:
Time
信号的方法。我建议选项 1。选项 3 是可悲的,你应该能够满足你在 Elm 中的要求。如果您是 Elm 新手,选项 2 可能不是一个好主意。选项 1 的工作量不大,邮件列表上的人也不会咬人 ;)
要详细说明选项 2,您是否应该这样做:
Signal Int
和一个传入端口,Signal Time
您可以在 JavaScript 中编写自己的动态时间函数。请参阅http://elm-lang.org/learn/Ports.elm 如果您想在 Elm 中执行此操作,则需要更丑陋的 hack:
dynamicFps frames =
let start = (0,0)
time = every millisecond -- this strains your program enormously
input = (,) <~ frames ~ time
step (frameTime,now) (oldDelta,old) =
let delta = now - old
in if (oldDelta,old) == (0,0)
then (frameTime,now) -- this is to skip the (0,0) start
else if delta * frameTime >= second
then (delta,now)
else (0,old)
in dropIf ((==) 0) 0 <| fst <~ foldp step start input
基本上,您记住一个绝对时间戳,尽可能快地询问新时间,并检查记住的时间和现在之间的时间是否足够大以适合您想要的时间范围。如果是这样,您发送该时间增量(fps 给出时间增量)并现在将其记住为新的时间戳。因为 foldp 会发出要记住的所有内容,所以您会同时获得新的 delta 和新的时间。所以使用fst <~
你只保留增量。但是输入时间(可能)比您想要的时间范围快得多,因此您也可以(0,old)
从foldp
. 这就是为什么有一个dropIf ((==) 0)
.
Elm 的类型系统 [本文的第 3.2 部分] 明确禁止嵌套信号。
据我了解 FRP,嵌套信号仅在提供某种讨人喜欢的情况下才有用(例如,monadic 'join' 函数)。如果不保留整个信号历史记录,就很难实施该操作。