Re: [elm-discuss] Re: Cmd Msg returned by init

2017-03-11 Thread Duane Johnson
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  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
>>  :
>> (a -> msg) -> Task
>> 

[elm-discuss] Re: Cmd Msg returned by init

2017-03-11 Thread Ilias Van Peer
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 
>  : 
> (a -> msg) -> Task 
>  Never 
>  a 
> -> 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 

[elm-discuss] Re: Cmd Msg returned by init

2017-03-10 Thread Richard Haven
I am just past beginner with Elm.

My current strategy is to treat Cmd Msg as a magic value that only the API 
can create (or Cmd.none). If you want a Cmd Msg, you have to call an API 
that returns it (e.g. HTML.send)

Cheers

-- 
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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[elm-discuss] Re: Cmd Msg returned by init

2017-03-08 Thread Martin Norbäck Olivers
sorry, I meant
init = update (FetchStatus 0) initialModel

Den onsdag 8 mars 2017 kl. 22:53:43 UTC+1 skrev Martin Norbäck Olivers:
>
> You don't need to send a command. Just "kick off" your initial model by 
> doing
> init = ( update (FecthStatus 0) initialModel, Cmd.none)
>
> Den onsdag 8 mars 2017 kl. 22:50:00 UTC+1 skrev 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 
>>  : 
>> (a -> msg) -> Task 
>>  
>> Never 
>>  a 
>> -> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.