There are a couple of bindings to moment.js I'd like to use for rendering time spans in my Halogen UI which have types something like
diffMins :: forall eff. Moment -> Moment -> Eff (now :: NOW | eff) Number
If I want to use this function in my UI like this:
H.span_ [H.text $ diffMins (fromEpoch_ 0) (fromEpoch_ myTimeStamp)]
But this is in Eff
so I can't.
What I can do is call into moment with this function:
js:
exports.duration_ = function (millis) {
return moment.duration(millis).humanize();
};
ps:
foreign import duration_ :: Number -> String
humanizeMilliseconds :: Milliseconds -> String
humanizeMilliseconds (Milliseconds n) = duration_ n
My question (or several) then:
Is it "cheating" to call into javascript without saying it's an Eff
. If not when is it considered ok and when not? I could squit either way and see these functions as side effecting or not.
If I couldn't have changed the way I'm calling moment, or indeed it is a bad idea, is there a way to do this in HTML
?
It is indeed not possible to perform anything effectful during renders in Halogen, as
HTML
is only data and render isstate -> HTML
.As Phil says in the comment, you don't have to use
Eff
in the signature of FFI functions though, if you're sure they perform no effects. In this case, it's probably safe, since it's basically arithmetic on dates - but there may be some locale-specific stuff going on? If so it's only a little bit dodgy, as at least it will always give the same result on the same machine, unless the OS clock is messed with. I'd be a little hesitant to accept that as being effect free, but if it was really a problem and I needed to do it I'd at least ensure the function is not exported so it can't be used anywhere else except in the exceptional circumstance.You could just do this in the component
eval
somewhere though and store the value in the component state -myTimeStamp
must already be in there, so you could compute this value at the same time? That way you're not recomputing a static value with eachrender
too.