Thank-you Ilias and Martin. Both approaches were novel and interesting to
me.
It turned out that in order to get data from the server, I had to create a
function with signature:
```
getStatus : Cmd Msg
getStatus =
Http.get (serverPrefix ++ "/api/status") decodeAll
|> RemoteData.sendRequest
|> Cmd.map GotStatus
```
So I was kind of going about it backwards. In the end, this is what my init
function looked like:
```
init : ( Model, Cmd Msg )
init =
( initialModel, getStatus )
```
The "leap" I was unable to make at first was that the same method that
`update` should call (on a timer) to trigger status updates from the server
is precisely the same function that `init` can call. So when I was trying
to call "RequestStatus", it was a synthetic (and unnecessary) message used
merely to get `update` to call `getStatus`:
```
-- Note: this is a simplified update function
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
RequestStatus time ->
( alertOnAnyFailure newModel, getStatus )
```
Just directly returning `getStatus` as the 2nd part of the tuple in the
`init` function is all that's necessary.
Duane
On Sat, Mar 11, 2017 at 8:39 AM, Ilias Van Peer <[email protected]> wrote:
> Let's take a step back, here.
>
> Conceptually, the `init` function is meant to say how to jumpstart your
> application. So what it should do, is provide the initial state of your
> model, and - optionally - telling the runtime to start executing some
> asynchronous task right away (a good example would be fetching some remote
> resource), as a Cmd.
>
> When the runtime receives such a Cmd, it will do what your commanded it to
> do, and then call your `update` function with the current state of the
> model and the Msg that resulted from your Cmd.
>
> Using `Task.perform` with a "no op" task to "trick" the runtime into
> calling your update feels wrong, as you say yourself. I'd argue that it's
> definitely abusing the the runtime, too.
>
> So, let's have a look at what you are trying to accomplish: you want to
> execute a function on your model, before declaring it "final". You could do
> that by calling `update` with the appropriate Msg from your init function,
> *or* you could split off that branch into a proper function that transforms
> your model.
>
> What you'd end up with, then, is something like this:
>
> ```
> init : (Model, Cmd msg)
> init =
> ( initialModel |> transformIt, Cmd.none)
> ```
>
> Your update function would call that exact same function - which means you
> could think of the update function like a sort of "translation" from
> messages to function calls that transform your model, rather than the one
> central place to bundle all your logic.
>
> Hope this helps :)
>
> Kr,
>
> Ilias
>
> Op woensdag 8 maart 2017 22:50:00 UTC+1 schreef Duane Johnson:
>
>> Preface: while I've been using Elm for a while, I've only just begun
>> using messages and commands, so it's ok to treat me like a newbie here.
>> This is a capture of my experience of Elm while trying to figure out how to
>> send an initial message.
>>
>>
>> I find the `Cmd` type a little confusing, especially in the init
>> function. Conceptually, I want to "kick off" an initial fetch of data from
>> client to server, and it would make intuitive sense if I were permitted to
>> do this:
>>
>> ```
>> init : (Model, Msg)
>> init =
>> { initialModel, FetchStatus 0 }
>> ```
>>
>> But instead, the type of `init` is required to be this:
>>
>> ```
>> init : (Model, Cmd Msg)
>> init =
>> { initialModel, ... }
>> ```
>>
>> When I get to this point, I need to look up the documentation on Cmd.
>> Having read the guide several months ago, I have a vague impression that I
>> may need to "perform" something to get my message into a Cmd type. I look
>> at the `Platform.Cmd` documentation, and I see there's a `Cmd` type which
>> looks like a constructor. So I try this:
>>
>> ```
>> init : (Model, Cmd Msg)
>> init =
>> { initialModel, Cmd (FetchStatus 0) }
>> ```
>>
>> But I get an error: "Cannot find variable `Cmd`". Having some experience
>> with Elm, I believe this may mean although Cmd is a type, its constructor
>> is not exposed.
>>
>> At this point, the `map` function looks a little promising, because it
>> takes some things that are not Cmd and produces `Cmd msg`, i.e. precisely
>> the type I'm looking for. However, it's not clear to me what the first
>> parameter to map is (a function that takes `a` and produces `msg`?) There's
>> no documentation on this `map` function.
>>
>> Then I peruse the docs some more ("maybe this is so common a thing that
>> it belongs in Basics? or maybe I missed something in Platform, since Cmd is
>> a submodule of Platform?") and arrive at the Task documentation, where I
>> see the "perform" signature:
>>
>> perform
>> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Task#perform> :
>> (a -> msg) -> Task
>> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Task#Task>
>> Never
>> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Basics#Never> a
>> -> Cmd
>> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Platform-Cmd#Cmd>
>> msg
>>
>> This looks promising as well, because it takes some things and produces a
>> `Cmd msg`. But the example in the documentation shows how to use `perform`
>> with `Time.now` which further confuses things because I just want to pass a
>> Time value to my FetchStatus, like it was meant to receive (not necessarily
>> a "now" value). If I try this:
>>
>> ```
>> init : ( Model, Cmd Msg )
>> init =
>> ( initialModel, Task.perform FetchStatus 0 )
>> ```
>>
>> I get
>>
>> ```
>> Function `perform` is expecting the 2nd argument to be:
>> Task.Task Never Time
>> ```
>>
>> So finally I realize that I need to pass a "succeed" task to my `perform`
>> call so I can create a `Cmd msg` of the type I need:
>>
>> ```
>> init : ( Model, Cmd Msg )
>> init =
>> ( initialModel, Task.perform FetchStatus (Task.succeed 0) )
>> ```
>>
>> Subjectively, this all feels more convoluted than it needs to be. At a
>> basic level, I want to communicate an initial model and an initial "kick
>> off" message. It's confusing that Task types are involved in constructing
>> Cmd types. This makes finding the right documentation difficult. In
>> addition, it isn't clear why a Cmd is needed at all--why not a Msg, or a
>> List Msg? Conceptually, this would be a lower barrier to entry.
>>
>> This is just a running journal of my experience trying to do a basic Elm
>> task (no pun intended). I hope it helps make the Elm experience better in
>> some way for others.
>>
>> Best,
>> Duane
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google Groups "Elm
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.