Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
478 views
in Technique[技术] by (71.8m points)

functional programming - How do I get the current time in Elm 0.17/0.18?

I had asked this question already:
How do I get the current time in Elm?

And answered it by writing my own (now deprecated) variant of start-app:
http://package.elm-lang.org/packages/z5h/time-app/1.0.1

Of course the Elm architecture has since changed, and my old way of doing things no longer works, because there are no signals or Time.timestamp.

So....

Suppose I build an app with the standard update function signature:
update : Msg -> Model -> (Model, Cmd Msg)

I'd like to timestamp my model with the time at update. One unacceptable almost-solution is to subscribe to Time.every. Conceptually this is not what I want. This is updating the model with time and also separately updating model with messages.

What I want is to be able to write an update function with signature:
updateWithTime : Msg -> Time -> Model -> (Model, Cmd Msg)


I started trying to solve this by adding some extra messages:
Msg = ... When | NewTime Time

And creating a new command:
timeCmd = perform (x -> NewTime 0.0) NewTime Time.now

So in any action, I can fire off an extra command to retrieve the time. But this gets messy and out of hand quickly.

Any ideas on how I can clean this up?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One option without having to do the time fetch on every update path would be to wrap your Msg in another message type that would fetch the time and then call your normal update with the time. This is a modified version of http://elm-lang.org/examples/buttons that will update a timestamp on the model with every update.

import Html exposing (div, button, text)
import Html.App exposing (program)
import Html.Events exposing (onClick)
import Task
import Time exposing (Time)


main =
  program { init = (Model 0 0, Cmd.none), view = view, update = update, subscriptions = (\_ -> Sub.none) }

type alias Model =
  { count: Int
  , updateTime : Time
  }

view model =
  Html.App.map GetTimeAndThen (modelView model)

type Msg
  = GetTimeAndThen ModelMsg
  | GotTime ModelMsg Time

update msg model =
  case msg of
    GetTimeAndThen wrappedMsg ->
      (model, Task.perform (\_ -> Debug.crash "") (GotTime wrappedMsg) Time.now)

    GotTime wrappedMsg time ->
      let
        (newModel, cmd) = modelUpdate wrappedMsg time model
      in
        (newModel, Cmd.map GetTimeAndThen cmd)

type ModelMsg = Increment | Decrement

modelUpdate msg time model =
  case msg of
    Increment ->
      ({model | count = model.count + 1, updateTime = time}, Cmd.none)

    Decrement ->
      ({model | count = model.count - 1, updateTime = time}, Cmd.none)

modelView model =
  div []
    [ button [ onClick  Decrement ] [ text "-" ]
    , div [] [ text (toString model.count) ]
    , button [ onClick  Increment ] [ text "+" ]
    , div [] [ text (toString model.updateTime) ]
    ]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...