keeping functions out of the model

353 views
Skip to first unread message

Joel Clermont

unread,
Oct 4, 2016, 10:53:07 PM10/4/16
to Elm Discuss
One recurring message I've heard lately is to keep functions out of your model. For example, in the elm-sortable-table docs:

One of the core rules of The Elm Architecture is never put functions in your Model or Msg types.


These libraries are really nice to use, but both put functions in the model. Should I be concerned that this will cause me problems later (like when 0.18 comes out)?

Are there animation libraries out there that avoid functions in models (or messages)? Thanks!

Max Goldstein

unread,
Oct 4, 2016, 11:19:51 PM10/4/16
to Elm Discuss
Hi, I'm the author of the second library you mentioned. It's natural to represent easing functions as, well, functions.

One way to avoid this would be to change (or supplement) elm-community/easing-functions to contain a big union type of all the easings possible. Then we could have a function that turns that type into an easing function. The animation models would contain a reference to this EasingDescription rather than the function itself.

There are some major downsides to this approach, not counting the work involved and library clutter. First, consumers of the animation library will have to know about the EasingDescription; it couples the two libraries and causes the abstraction to leak. Second, animations will only be able to use easing functions that have descriptions, not any easing function they like. Finally, my library allows animations to be undone or retargeted, which involves working with the easing function in ways beyond the description.

So, a better approach might be to sample the easing function provided (perhaps 100 times in 0..1) and use linear interpolation between these samples. Many samples gives a more accurate animation but consumes more memory. This approach also means that retrieving an easing function from an animation will be inexact.

Even so, until someone tells me that everything will explode if you have functions in your model, I'm going to sit tight.

Noah Hall

unread,
Oct 4, 2016, 11:23:38 PM10/4/16
to elm-d...@googlegroups.com
Functions in your model makes it harder to serialize your model. It
also can cause issues when trying to print it out and related things.
It makes it hard to perform eq on. It is better to just store the
things needed to create the function, then just pass those args to the
function when you need it. This is a problem that we have had in
production. Models are for data, not for functions.
> --
> 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.

Max Goldstein

unread,
Oct 5, 2016, 1:56:04 AM10/5/16
to Elm Discuss
Serialization: animations are view state. They can safely be left out of a serialized and persisted model.

Print out the model: True, but if you're using animation in an app, you're beyond poking at the model in the REPL.

Harder to equate: My animation library provides an "equals" function. In addition to sampling the easing function, it accounts for a few other ways animations can have different representations but be considered equal (e.g. start at time t with delay k == start at time t+k with no delay).

"just store the things needed to create the function" -> This is essentially the "EasingDescription" idea I talked about above. The problem is that easing functions can be created in many way (sinusoids, polynomials, exponentials, bounces) and I want to allow the client to specify any function.

Zinggi

unread,
Oct 5, 2016, 4:01:25 AM10/5/16
to Elm Discuss
I think you could create an animation library that doesn't store any functions in its model and still be able to let a user provide whatever easing function they want.

E.g. remove the ease key from your AnimRecord and let all functions that currently take an Animation have an additional parameter easingFunction:

animate : EasingFunction -> Time -> Animation -> Float

This way a user of your library doesn't have to put any functions in their model and you get both a function free model and endless customization by providing whatever easing function a user needs.

Am I missing something?

Zinggi

unread,
Oct 5, 2016, 4:03:42 AM10/5/16
to Elm Discuss
This also has the added benefit that you can then use the same animation with different easing functions without having to duplicate the whole Animation record.

Mark Hamburg

unread,
Oct 5, 2016, 6:57:44 AM10/5/16
to elm-d...@googlegroups.com
On Oct 5, 2016, at 5:22 AM, Noah Hall <enal...@gmail.com> wrote:
>
> It makes it hard to perform eq on.

This is the big one from my standpoint. To optimize lazy views (and memory/gc behavior), I've at times written "smart" update functions that check for equality with existing values before constructing new values. This then started blowing up with a runtime exception caused by comparing functions for equality. Now, I'm paranoid and both avoid functions in models and equality comparisons because someone else may not have exhibited one or the other of these forms of caution.

It would be nice if Elm would treat functions that aren't obviously equal as unequal but I recognize that this could lead to compiler optimizations changing the behavior of programs which isn't great either.

Mark

Max Goldstein

unread,
Oct 5, 2016, 12:14:37 PM10/5/16
to Elm Discuss
Zinggi: My objection is that the easing function is part of the logical identity of the animation. It's tedious to keep track of the function separately. Also, animation concepts like velocity and retargetting rely on the easing function. "The same animation with a different easing function"… is not the same animation.

Joel Clermont

unread,
Oct 5, 2016, 12:17:09 PM10/5/16
to Elm Discuss
Thank you so much for all the replies, especially to Max for his insights on decisions made in his animation library.

I feel like I'm a bit closer to understanding the issues here, but I still have some fuzzy edges:

Serialization: If I'm manually serializing my model to persist somewhere, I can easily skip over an animation property. But what about the stuff demo'd in 0.18? That's automatically serializing my model while debugging. Does anyone know if I'll be unable to use that sort of tooling because I have a function in my model or message?

Equality: Similar to serialization, is this just a matter of me having to be smarter when doing manual optimizations that look at model equality? Or is there something in the runtime/compiler that is going to break or be less optimized as a result?

I suppose some of this is trying to predict the future. It just makes me nervous to hear from Evan "definitely don't do this thing" but not fully understand the implications of selectively ignoring that advice by pulling in one of the really nice animation libraries.

Max Goldstein

unread,
Oct 5, 2016, 9:39:14 PM10/5/16
to Elm Discuss
Thank you for your kind words, Joel.

If 0.18 debugging totally breaks an animations, I'll think of something. These are some valid concerns but I haven't seen a smoking gun yet.

Mark Hamburg

unread,
Oct 5, 2016, 10:12:21 PM10/5/16
to elm-d...@googlegroups.com

> On Oct 5, 2016, at 6:17 PM, Joel Clermont <jcle...@gmail.com> wrote:
>
> Equality: Similar to serialization, is this just a matter of me having to be smarter when doing manual optimizations that look at model equality? Or is there something in the runtime/compiler that is going to break or be less optimized as a result?

If you (or anyone else contributing code to your project including any public Elm packages) use == with values that might contain functions, you have a lurking runtime error waiting to happen.

Spreading the paranoia,
Mark

Reply all
Reply to author
Forward
0 new messages