Upgrading to 0.19
To make the process as smooth as possible, this document outlines all the things you need to do to upgrade to 0.19.
- Command Line
elm.json- Changes
--optimize- Compiler Performance
- Parse Errors
- Stricter Record Update Syntax
- Removed User-Defined Operators
Note: You can try out
elm-upgradewhich automates some of the 0.18 to 0.19 changes. It is also in an alpha stage, and Aaron has said it makes sense to talk things through here.
Command Line
There is now just one elm binary at the command line. The terminal commands are now:
# 0.19 # 0.18
elm make # elm-make
elm repl # elm-repl
elm reactor # elm-reactor
elm install # elm-package install
elm publish # elm-package publish
elm bump # elm-package bump
elm diff # elm-package diffelm.json
elm-package.json becomes elm.json which is specialized for applications and packages. For example, it helps you lock your dependencies in applications and get broad dependency ranges in packages.
See the full outlines here:
elm.jsonfor applicationselm.jsonfor packages
Both are quite similar to the elm-package.json format, and elm-upgrade can help you with this.
Changes
Functions Changed
String.toInt : String -> Maybe Int(notResultanymore)String.toFloat : String -> Maybe Float(notResultanymore)Basics.toStringbecomesDebug.toString,String.fromInt, andString.fromFloat.Basics.rem 451 10becomesremainderBy 10 451451 % 10becomesmodBy 10 451style : List (String, String) -> Attribute msgbecomesString -> String -> Attribute msgHtml.beginnerProgrambecomesBrowser.sandbox.Html.programbecomesBrowser.elementandBrowser.document.
Modules Moved
Json.EncodeandJson.Decodemoved toelm/jsonTimeandDatemoved toelm/timewith a significantly improved APIRandommoved toelm/randomwith a better implementation and a few new functionsRegexmoved toelm/regexwith a much clearer README
Packages Moved
elm-lang/*moved toelm/*evancz/url-parsermoved toelm/urlwith a simpler and more flexible APIelm-tools/elm-parsermoved toelm/parserwith speed boost when compiling with the--optimizeflagelm/browsercombines and simplifies the following 0.18 packages:elm-lang/navigationwith smoother APIselm-lang/domwith ability to get node positions and dimensions.elm-lang/mousewith decoderselm-lang/windowelm-lang/keyboarduses decoders like thiselm-lang/page-visibilityelm-lang/animation-frame
Functions Removed
uncurrycurryflip
Prefer named helper functions in these cases.
--optimize
You can now compile with elm make --optimize which enables things like:
- Reliable field name shortening in compiled assets
- Unbox things like
type Height = Height Floatto just be a float at runtime - Unbox
Charvalues - Use more compact names for
typeconstructors in compiled assets.
Some of these optimizations require "forgetting information" that is useful while debugging, so the Debug module becomes unavailable when you add the --optimize flag. The idea being that you want to be shipping code with this flag (like -O2 in C) but not compiling with it all day in development.
Compiler Performance
I did a bunch of performance optimizations for the compiler itself. For example:
- I rewrote the parser to be very significantly faster (partly by allocating very little!)
- I revamped how type inference looks up the type of foreign variables to be
O(1)rather thanO(log(n)) - I redid how code is generated to allow DCE with declarations as the level of granuality
- Packages are downloaded once per user and saved in
~/.elm/ - Packages are built once for any given set of dependencies, so they do not contribute to build times of fresh projects.
Point is, the compiler is very significantly faster!
Parse Errors
Part of rewriting the parser was making nicer parse errors. Many people only really see them when getting started, and rather than saying "man, these are terrible" they think "man, programming is hard" leading to a big underreporting of quality issues here. Anyway, please explore that a bit and see if you run into anything odd!
Stricter Record Update Syntax
It used to be possible for { r | x = v } to change the type of field x. This is no longer possible. This greatly improves the quality of error messages in many cases.
You can still change the type of a field, but you must reconstruct the record with the record literal syntax, or with a record constructor.
The idea is that 99.9% of uses get a much better experience with type errors, whereas 0.1% of uses become somewhat more verbose. As someone who had a bit of code that changed record types, I have found this to be a really excellent trade.
Removed User-Defined Operators
It is no longer possible to define custom operators. For example, someone defined:
(|-~->) : (a -> a1_1 -> a3) -> (a2 -> a1_1) -> a -> a2 -> a3They are still able to define that function, but it will need a human readable name that explains what it is meant to do. The reasoning behind this decision is outlined in detail in this document.
Notes:
toString— A relatively common bug was to show anIntin the UI, and then later that value changes to something else.toStringwould just show wrong information until someone noticed. The newString.fromIntandString.fromFloatensure that cannot happen. Furthermore, more elaborate types almost certainly need localization or internationalization, which should be handled differently anyway.