Preamble
fps Mouse.x
Results in a type-error that fps requires an Int
, not a Signal Int
.
lift fps Mouse.x : Signal (Signal Int)
You are correct there. As CheatX's answers mentions, you cannot using these "nested signals" in Elm.
Answer to your question
It seems like you're asking for something that doesn't exist yet in the Standard Libraries. If I understand your question correctly you would like a time (or fps) signal of which the timing can be changed dynamically. Something like:
dynamicFps : Signal Int -> Signal Time
Using the built-in functions like lift
does not give you the ability to construct such a function yourself from a function of type Int -> Signal Time
.
I think you have three options here:
- Ask to have this function added to the Time library on the mailing-list. (The feature request instructions are a little bloated for a request of such a function so you can skip stuff that's not applicable)
- Work around the problem, either from within Elm or in JavaScript, using Ports to connect to Elm.
- Find a way to not need a dynamically changing
Time
signal.
I advise option 1. Option 3 is sad, you should be able to what you asked in Elm. Option 2 is perhaps not a good idea if you're new to Elm. Option 1 is not a lot of work, and the folks on the mailing-list don't bite ;)
To elaborate on option 2, should you want to go for that:
- If you specify an outgoing port for
Signal Int
and an incoming port for Signal Time
you can write your own dynamic time function in JavaScript. See http://elm-lang.org/learn/Ports.elm
If you want to do this from within Elm, it'll take an uglier 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
Basically, you remember an absolute timestamp, ask for the new time as fast as you can, and check if the time between the remembered time and now is big enough to fit the timeframe you want. If so you send out that time delta (fps gives time deltas) and remember now as the new timestamp. Because foldp sends out everything it is to remember, you get both the new delta and the new time. So using fst <~
you keep only the delta. But the input time is (likely) much faster than the timeframe you want so you also get a lot of (0,old)
from foldp
. That's why there is a dropIf ((==) 0)
.