Getting current time

I’m struggling to understand how to get the current time with Elm. I would expect that Time.now would return a Time or Int or Float but instead it is the ever-confusing Task. I want to use the current Posix time in milliseconds to generate keys for a Dict when creating new entries. I’m hopeless with this concept.

There is short example of getting time here in official guide: https://guide.elm-lang.org/effects/time.html

I’ve read through that several times but don’t understand how to translate constantly updating every second for just getting the time when I click a button. My problem is not with the Time module per se, but with Tasks in general. I don’t understand the need for them and what they accomplish. When I say “Elm, I want the current time” I expect Elm to return the current time. Instead Elm returns some Task awaiting some other ingredient that I don’t know how to supply.

Here is small example in Ellie about how to add items to Dict on button press, using current time as key: https://ellie-app.com/3N8Pk6BZy39a1

6 Likes

Functions in Elm are pure functions without any side effects. Only information functions can access is their parameters and nothing else. So it’s impossible to create a function getCurrentTime in Elm as functions can never access the clock.

Only Elm runtime has access to clock, which is why you need a Task which gets the time from Elm runtime.

3 Likes

Thank you for the illustrative example, very helpful. I guess I’m still just confused by the need to expose that need for the Task. Are there any instances in which you would call Time.now and not perform a Task of some sort? If not, why not have the Time module build that in?

No, I don’t think there is any case when you would use Time.now without Task.

But there are other use cases for Time.now than just simply getting current time. For example in my time-syncing app I use three tasks together:

  1. get request start time (Time.now)
  2. fetch time from server (Http.get)
  3. get request end time (Time.now)

And then I calculate client/server clock offset from these values.

So since there are different ways to use tasks like Time.now, it makes sense to put all common Task related code in it’s own package and not complicate for example Time package with such code, even if that does make simple case of e.g. getting current time a bit more complicated that it needs to be (i.e. must use Task.perform with Time.now).

1 Like

In Elm, all functions must return the same value given the same arguments. Functions that have this property are called pure functions and in Elm all functions must be pure.

Functions like increment are pure. You can call increment 2 as many times as you want in any context and you will always get 3 back.

The problem comes with functions like rand or now. The entire purpose of these functions is to return different values every time they are called. These functions would be useless if they always returned the same value. However, to have functions like that would violate Elm requirement that all functions must be pure.

Elm’s solution is an approach called effects as data. Instead of actually doing the work of calculating a random value or the current time ourselves, we generate a “request” for the Elm runtime to do that work. This “request” (a Task or Cmd value) does not immediately execute. Instead it is a piece of data that can be returned, passed around, and transformed. Eventually we pass it to the Elm runtime (by returning it from the root update function) and the runtime will execute it.

So what does all this fanciness this buy us? Time.now and Random.generate now always return the same value (the “request” to the runtime) for the same arguments. Time.now always returns the same task. We’ve changed non-pure functions into pure functions!

7 Likes

I guess this is a case in which ideological purity is at odds with the secondary goal of ease of use. Thanks for the explanation.

Is your app code public? I’d like to look through it if so. Thanks for taking the time to help me out.

Yes, it’s “time-check” at elm-examples (Main.elm). Live version is here.

2 Likes

Yeah true. But all the good stuff about Elm (no runtime exceptions, easy refactoring, the feeling of “if it compiles it works”) comes from its guarantees. And guarantees have to be absolute or they don’t work. To quote one of Richard Feldman’s talks, “just one drop if urine in a barrel of water gives you a barrel of urine-water”.
The trade-off is that you get some simple cases that feel overly complicated. Time and randomness are the two main ones I can think of.

3 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.