Very interesting work!
I think that one might (naively) have expected the `Location` to be exposed as a `Sub Location`. One could, then, use the sort of `Parser` which you provide for (to `map` the `Sub Location` to a `Sub msg`), and then supply the `Sub msg` when initializing the `Program` (as you might with any other permanent subscription).
Instead, the module provides for a different way of constructing a `Program` -- that is, an alternative to `Html.App.program` or `Html.App.programWithFlags`.
What this permits, at first glance, is providing for an entirely separate function to handle updates from navigation -- that is, a `urlUpdate` function which is separate from the usual `update` function. (The naive approach I mentioned above would only have an `update` function, with the location changes mapped to messages that the `update` function understands).
What problem does a separate `urlUpdate` function solve? My guess is that it solves a circularity problem. Consider (as in the example provided) incrementing or decrementing a counter. In the `update` method, in addition to updating the model, one wants to issue a command to change the URL. In the `urlUpdate` method, you just want to update the model. You don't want to change the URL, because that would trigger another round of `urlUpdate` -- you'd be in an infinite loop.
So, the separate `urlUpdate` function is a kind of a reminder not to issue further commands to change the location inside the `urlUpdate`. (Or, at least usually not -- I suppose there might be some scenarios where you might actually want a kind of "redirect", so long as the redirecting terminates eventually).
So, that's an interesting solution. Are there any disadvantages to it? I suppose that there are a couple of potential disadvantages.
One, I suppose, is a question of composability. This strategy is kind of a singleton -- at least, it's hard to see how you could use this strategy again, and then compose the two. But, perhaps you won't need this strategy again, or you'll figure out how to cross that bridge when you come to it.
The other potential disadvantage is a kind of duplication between the logic needed for `urlUpdate` and `update` -- both logic in the sense of dispatch to sub-components, and logic in the sense of the logic for the actual model changes. Though, I suppose that problem is relatively easy for clients of the library to solve -- one could imagine a third function, `universalUpdate`, which takes a `Bool` parameter that indicates whether the change is coming from `update` or `urlUpdate`. Then, both `update` and `urlUpdate` can call `universalUpdate`, which would know whether to change the URL via the `Bool` parameter. Or something like that -- it seems like a solvable problem for users of the library.
I suppose that is how one could solve the circularity issue in the "naive" subscription approach as well. That is, one might include, in the `Msg` type, an indication of whether the `Msg` is coming from "normal" user action or from the URL change. (And, thus, know, within the `update` method, whether to issue a URL change command).
Anyway, I hope I have not offered any opinions in the above comments -- I don't really have any opinions yet, just a few interesting things that I noticed.
--
Ryan Rempel