Task that don't fail and Cmd

558 views
Skip to first unread message

Zinggi

unread,
May 15, 2016, 12:30:28 PM5/15/16
to Elm Discuss
I need to get the window dimensions, so I'm doing:

type Msg = GetScreenSizeFailed | UpdateScreenSize Size
Task.perform (always GetScreenSizeFailed) UpdateScreenSize Window.size

I was under the impression that getting the window dimension will never fail, so it seems strange that I need GetScreenSizeFailed at all.
Is there a function that gives me a Cmd, but only has a success case? Something with which I could do:

Task.performSucceed UpdateScreenSize Window.size

Such a function would only call update if the Task succeeds and if it fails, just do nothing. Even though failing should be impossible here.

Also, why does Window.size return a Task and not a Cmd?


Peter Damoc

unread,
May 15, 2016, 12:40:22 PM5/15/16
to Elm Discuss
Maybe that task can fail if you run the Elm program with .worker rather than .embed or .fullscreen.

In any way, for regular programs you can just reuse that UpdateScreenSize Tag for fail too or use a generic (\_ -> NoOp)

 


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



--
There is NO FATE, we are the creators.
blog: http://damoc.ro/

Janis Voigtländer

unread,
May 15, 2016, 12:42:36 PM5/15/16
to elm-d...@googlegroups.com

Maybe that task can fail if you run the Elm program with .worker rather than .embed or .fullscreen.

No, that task definitely cannot fail. Otherwise it would not be able to have the following type in the Window module:

size : Task x Size

Janis Voigtländer

unread,
May 15, 2016, 12:47:36 PM5/15/16
to elm-d...@googlegroups.com

You should be able to define performSucceed yourself (and with a built-in guarantee that the failing case will definitely not occur):

performSucceed : (a -> msg) -> Task Never a -> Cmd msg
performSucceed = Task.perform never

never : Never -> a
never n = never n

which (in particular never) may look daunting, but isn’t. That never function could be hidden away from you, see https://github.com/elm-lang/core/pull/593.

Zinggi

unread,
May 15, 2016, 1:52:34 PM5/15/16
to Elm Discuss
Thank you very much!
This works and is exactly what I wanted.

However I don't understand how it works -.-
That never function looks crazy indeed. Why does it use infinite recursion and not this:
never n = Debug.crash "Well, we're doomed \_(ツ)_/"

Also regarding my second question, why does Window.size not return a Cmd?
What benefits does a Task that cannot fail have over a Cmd?

Cheers

Joey Eremondi

unread,
May 15, 2016, 2:00:17 PM5/15/16
to elm-d...@googlegroups.com
Why does it use infinite recursion and not this:

Either would be fine. The key is the definition of the type Never:
type Never = Never Never
It's impossible to create a value of this type.

The function will never be called, so it doesn't matter how you define it. This way, the generated code doesn't need to set up the wiring for throwing an error.

Janis Voigtländer

unread,
May 15, 2016, 2:16:48 PM5/15/16
to elm-d...@googlegroups.com

About this:

However I don’t understand how it works -.-> That never function looks crazy indeed. Why does it use infinite recursion and not this:

never n = Debug.crash “Well, we’re doomed _(ツ)_/“

Joey has provided the answer.

About this:

Also regarding my second question, why does Window.size not return a Cmd?
What benefits does a Task that cannot fail have over a Cmd?

Tasks are more composable, which you might need in some situations (combining the Window.size with some other task before turning the result into a Cmd). The key here is that nothing like http://package.elm-lang.org/packages/elm-lang/core/4.0.0/Task#andThen exists for Cmd.

Zinggi

unread,
May 15, 2016, 4:27:24 PM5/15/16
to Elm Discuss
Thanks Joey and Janis, but I still don't really understand when to use Task x and when to use Cmd.

I get that Tasks are more composable than Cmds, but the flexibility (and complexity) seems only necessary if a Task can fail.

Basically, I can't think of any actual use of Window.size that doesn't use the just defined performSucceed function.
Also, the random library uses a Cmd for something very similar, so I expected the Window.size would also be a Cmd.
Time.now is another such example where I would have expected a Cmd, but it uses a Task instead.

So, what's the difference in usage between a Task x Something and Cmd Something?

Janis Voigtländer

unread,
May 15, 2016, 4:40:01 PM5/15/16
to elm-d...@googlegroups.com

Let’s say you want to make an http request where the url to request should depend on the current time. You can build a task that does this by combining Time.now and Http.getString. Something like Time.now `andThen` \time -> Http.getString (queryStringBuildFrom time). Then you turn that combined task into a Cmd and return it from your update function. If you were to try to do the same with just Cmds, you would have to do Time.now, then have an extra round of the update function in which you receive the resulting time, turn it into an Http request Cmd, send that off, and wait for its result. That’s not necessarily what you want, the extra update round, and no guarantee that no other message occurs in between. (That is, with the Cmd-only thing, you don’t even know that the two involved update rounds happen directly after each other. With Task, you have built a thing consisting of time getting and request sending that will definitely happen directly one after the other. At least with the current state of the Task and scheduler implementation.)

Janis Voigtländer

unread,
May 15, 2016, 5:09:30 PM5/15/16
to elm-d...@googlegroups.com

Actually, maybe a more useful description would frame this not as what Cmd does not have that Task has, namely andThen, but instead frame it as what Cmd offers in addition. It’s the “managed effects” aspect discussed at http://guide.elm-lang.org/effect_managers/. The two examples you mentioned, Time.now and Random.generate, are nor actually as similar as you seem to assume. To support Time.now, the implementation doesn’t need any effect management in the background. It just asks the operating system for the current time, and done. To support Random.generate, the implementation does need to do effect management (magic) in the background. Namely, it needs to keep track of a hidden seed for the random generator. That must be preserved/propagated over several calls throughout the program’s life. That would not be possible with a Task, but it is possible with a Cmd, thanks to the concept of effect managers. That’s also the reason why a Task can be turned into a Cmd, but a Cmd can’t be turned into a Task. So when looking through the available core and platform libraries, and wondering about why some things are Tasks and others are Cmds, the reasoning in my understanding is that something is a Task if it can be, if it can be implemented without effect management magic behind the scenes, whereas something is a Cmd if it has to be, if it could not be implemented without hidden effect management.

Zinggi

unread,
May 15, 2016, 6:27:30 PM5/15/16
to Elm Discuss
Thank you very much!
Both your explanations make perfect sense and cleared that up for me.

Tobias Hermann

unread,
May 16, 2016, 3:54:21 AM5/16/16
to Elm Discuss
I also have to say thank you, because I had exactly the same question, and this thread helped me a lot. :)

Eric Lam

unread,
May 16, 2016, 12:22:31 PM5/16/16
to Elm Discuss
I have a semi-related question/comment while upgrading my website to 0.17.0:

Is the general convention for Msg to not have any maybes anymore?

My website has Cmds which have maybe parameters and I'm unsure if I should create additional Cmds for the never cases when I was handling it as a maybe. It makes sense to have explicit handling of failed tasks, but on the other-hand, it's also inconvenient to have Cmds which leads to nothing.
Reply all
Reply to author
Forward
0 new messages