Just a quick note related to the topic, you may be interested in 5 minutes from a talk by Kris Jenkins regarding Maybes and union types for representing async data.
This is something I’ve written and spoke about and I believe @joelq has too. There are other ways of eliminating Maybes if that is truly your end goal.
One of the end goals is to use a primitive instead of a union type. The whole app makes more sense if you are dealing with a primitive, instead of dealing with cases or passing values as arguments. If you don’t have that value is because the app it’s not ready.
Right now we have an inner app with primitives and an outer app that deals with fetching and union types. It works for us, but I don’t think that is idiomatic and also more complex.
Do you mean static data, generated and embedded in the HTML (or imported via javascript)?
Or do you mean dynamic data, i.e. doing a fetch from javascript before initializing the elm app?
The first seems fine to me, the second seems less safe than doing it within Elm.
Note that if you are passing in the flags data as Json.Value, I think you are still inside a Result , unless you Debug.crash on a decode failure (which won’t be allowed in production apps in the future).
I have done it and it works fine. Just (as always) be aware of the edgecases. You don’t want your app to fail init because a list is null instead of empty.
We are doing something like this. We treat the flags parameter passed into the init function as a Value type then apply a custom decoder to it using decodeValue to produce a “configuration” record with several fields containing primitives.
In the event that the decoding fails, we set an error value in the model that notifies the user that the app could not be initialized correctly (and display some debug information produced by the Err result). This approach works very well for data that must be generated from your back end and is required to intersection initialize the app.
We do this all over the place at work. Our flag type is always Json.Decode.Value. We run a decoder on it to decode the data from the server. If it succeeds, we have our initial Model and proceed as normal. If it fails, we render an error message to the user and send an error report to our logging service (Rollbar).
I also do this in some of my projects. I have the initial user data rendered into the main html page via a phoenix template and load it all in Elm through the flags. Works great.
We also rely heavily on this approach. We have loads of configuration that is described in YAML, combined in various ways during the build step based on feature flags and cli parameters, translated to json, further combined with a handful of flags written to the response from the Razor page, and then finally sent to the Elm app as a Json.Decode.Value where it can be chunked out into the various feature configs. Like @rtfeldman mentions, if any decoding of a config chunk fails for a particular feature, we render an error message where appropriate and report to Rollbar.