如何根据另一个信号参数化一个信号? 例如假设我想根据鼠标的x位置修改fps。类型是:
Mouse.x : Signal Int
fps : number -> Signal Time
我怎么能让Elm理解这个伪代码的内容:
fps (Mouse.x) : Signal Time
显然,lift
在这种情况下不起作用。我认为结果将是Signal (Signal Time)
(但我对榆树来说还是一个新手)。
谢谢!
答案 0 :(得分:4)
fps Mouse.x
导致类型错误的结果是fps需要Int
,而不是Signal Int
。
lift fps Mouse.x : Signal (Signal Int)
你是对的。正如CheatX的回答所提到的,你不能在榆树中使用这些“嵌套信号”。
好像你要求Standard Libraries中尚不存在的东西。如果我正确理解你的问题,你会想要一个时间(或fps)信号,其时间可以动态改变。类似的东西:
dynamicFps : Signal Int -> Signal Time
使用lift
之类的内置函数不能让您自己从类型Int -> Signal Time
的函数构造这样的函数。
我认为你有三种选择:
Time
信号的方法。我建议选项1 。选项3很难过,你应该能够满足你在榆树中的要求。如果你是榆树的新手,选项2可能不是一个好主意。选项1不是很多工作,邮件列表上的人不会咬人;)
要详细说明选项2,您是否应该这样做:
Signal Int
的传出端口和Signal Time
的传入端口,则可以在JavaScript中编写自己的动态时间函数。请参阅http://elm-lang.org/learn/Ports.elm 如果你想从榆树内部做到这一点,那将是一个丑陋的黑客攻击:
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
基本上,你记得一个绝对时间戳,尽可能快地询问新时间,并检查记忆时间和现在之间的时间是否足够大以适应你想要的时间范围。如果是这样,你发出时间delta(fps给出时间增量)并记住现在作为新的时间戳。因为foldp发出了要记住的所有内容,所以你得到了新的delta和新的时间。因此,使用fst <~
只保留delta。但输入时间(可能)比您想要的时间段快得多,因此您从(0,old)
获得了大量foldp
。这就是dropIf ((==) 0)
的原因。
答案 1 :(得分:0)
Elm的类型系统明确禁止嵌套信号[{3}}的第3.2部分。
据我了解FRP,嵌套信号仅在提供某种奉承时才有用(例如,monadic'join'函数)。如果不保留整个信号历史记录,很难实现该操作。