Upgrade Instructions/0.16
Upgrading to 0.16
Upgrading should be pretty easy. Everything is quite mechanical, so I would not be very afraid of this process.
Update elm-package.json
First thing you want to do is update your elm-package.json file. The fields that need work are repository, elm-version, and dependencies.
If you have some dummy information in repository, something like https://github.com/USER/PROJECT.git, you will need to change it such that the project is all lower case. This should work: https://github.com/user/project.git.
Here is a working elm-version:
{
"elm-version": "0.16.0 <= v < 0.17.0"
}Here are the latest bounds for a bunch of dependencies.
{
"dependencies": {
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.1 <= v < 3.0.0",
"evancz/elm-html": "4.0.2 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0",
"evancz/elm-markdown": "2.0.0 <= v < 3.0.0",
"evancz/elm-svg": "2.0.1 <= v < 3.0.0",
"evancz/start-app": "2.0.2 <= v < 3.0.0"
},
}The easiest way to get this all set up is to remove everything from dependencies and just install the things you need one at a time with elm-package install.
Updating Syntax
The major syntax changes are:
| feature | 0.15.1 | 0.16 |
|---|---|---|
| field update | { record x | { record x = 42 } |
| field addition | { record x = 42 } | removed |
| field deletion | { record - x } | removed |
| record constructors that add fields | type alias Named r = | |
| { r name : String } |
-- generates a function like this:
-- Named : String -> r -> Named r | type alias Named r =
{ r name : String }
Generates no function. Field addition is gone. A function
will still be generated for "closed" records though. |
| field parameters | type alias Foo =
{ prefix : String -> String }
foo : Foo
foo = { prefix x = "prefix" ++ x } | type alias Foo =
{ prefix : String -> String }
foo : Foo
foo = { prefix = \x-> "prefix" ++ x } |
| multi-way if | if x "left"
x > 0 -> "right"
otherwise -> "neither" | if x 0 then
"right"
else
"neither" |
The most common by far should be the record update change. That was the only syntax that used the <- operator, so you can pretty safely do a find-and-replace from <- to = and be all set.
The multi-way if is also pretty easy. You just translate it into the equivalent if/then/else construct. As you are doing this, notice the style used. It should look quite a bit like Python or any C-like language really. You start with an if and do else if until you are done. The body of each branch should be indented and things look way nicer if you have a blank line between each branch. I sometimes put a blank line above and below each branch, especially when the branch is more complex.
If you are using field addition and deletion, it is possible to translate your code into:
- A union type that models things with a simpler API, like in this case.
- Nesting records instead of adding things onto them. Rather than adding a field, create an outer record that contains a field for the two things you are trying to put together. This seems to lead to nicer code in the long run.
Incomplete Pattern Matches
As of 0.16, incomplete pattern matches are caught at compile time as errors. This is true both of case expressions and function arguments.
As I updated things, I ran into this only when I had been tricky with Maybe and List where I knew something about their structure based on some incidental details. The nicest example of this was some code in package.elm-lang.org where the priority has often been "get it working" over "excellent quality code".
The compiler should give you pretty nice hints in all these cases, so I think the best advice is just to expect this sort of thing and treat it as an oppurtunity to clean your code up a bit where you were being tricky.
Updating Library Usages
There is not actually a lot that changed in elm-lang/core and in evancz/* libraries.
The most noticable removals will be:
Basics.otherwiseSignal.(<~)Signal.(~)
otherwise is gone because it is very useless without the multi-way if syntax.
Removing (<~) and (~) is in the spirit of "infix functions should be avoided" and the overall move towards removing redundant and ugly syntax in this release. You can instead use Signal.mapN to fill the void here. If you are combining a ton of signals, you can redefine the equivalent of (~) like this:
andMap : Signal (a -> b) -> Signal a -> Signal b
andMap =
Signal.map2 (<|)Otherwise it is pretty much all small bug fixes and improvements to documentation.
Upgrade Instructions/0.17
Upgrading to 0.17
Upgrading should be pretty easy. Everything is quite mechanical, so I would not be very afraid of this process.
Update elm-package.json
Some core packages have been renamed:
evancz/elm-htmlis nowelm-lang/htmlevancz/elm-svgis nowelm-lang/svgevancz/virtual-domis nowelm-lang/virtual-dom- The functionality of
evancz/start-appnow lives inelm-lang/htmlinHtml.App - The functionality of
evancz/elm-effectsnow lives inelm-lang/coreinPlatform.* - The functionality of
Graphics.*now lives inevancz/elm-graphics
So the first thing you want to do is update your elm-package.json file. Here is one that has been properly updated:
{
"version": "1.0.0",
"summary": "let people do a cool thing in a fun way",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"src"
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "4.0.0 <= v < 5.0.0",
"elm-lang/html": "1.0.0 <= v < 2.0.0",
"evancz/elm-http": "3.0.1 <= v < 4.0.0",
"evancz/elm-markdown": "3.0.0 <= v < 4.0.0"
},
"elm-version": "0.17.0 <= v < 0.18.0"
}The only changes should be in the dependencies and elm-version fields where you need to update constraints. The easiest way to get this all set up is to update elm-version by hand, and then remove everything from dependencies so you can install the dependencies you still need one at a time with elm package install.
Updating Syntax
The major syntax changes are:
| feature | 0.16 | 0.17 |
|---|---|---|
| module declaration | module Queue (..) where | module Queue exposing (..) |
This is a super easy change, so we will add a link to an auto-upgrade tool here when one exists.
`Action` is now `Msg`
The Elm Architecture tutorial uses the term Action for the data that gets fed into your update function. This is a silly name. So in 0.17 the standard name is message.
-- 0.16
type Action = Increment | Decrement
-- 0.17
type Msg = Increment | DecrementThe idea is that your app is receiving messages from the user, from servers, from the browser, etc. Your app then reacts to these messages in the update function.
No More `Signal.Address`
The most common thing in your code will probably be that Signal.Address no longer exists. Here is a before and after of upgrading some typical view code.
-- 0.16
view : Signal.Address Action -> Model -> Html
view address model =
div []
[ button [ onClick address Decrement ] [ text "-" ]
, div [ countStyle ] [ text (toString model) ]
, button [ onClick address Increment ] [ text "+" ]
]
-- 0.17
view : Model -> Html Msg
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [ countStyle ] [ text (toString model) ]
, button [ onClick Increment ] [ text "+" ]
]This change is pretty simple. Any occurance of address just gets deleted. In the types, you see the addresses removed, and Html becomes Html Msg. You can read Html Msg as "an HTML node that can produce messages of type Msg". This change makes addresses unnecessary and makes it much clearer what kind of messages can be produced by a particular block of HTML.
The Signal.forwardTo function is replaced by Html.App.map. So you may need to make changes like this:
-- 0.16
view : Signal.Address Action -> Model -> Html
view address model =
div []
[ Counter.view (Signal.forwardTo address Top) model.topCounter
, Counter.view (Signal.forwardTo address Bottom) model.bottomCounter
, button [ onClick address Reset ] [ text "RESET" ]
]
-- 0.17
view : Model -> Html Msg
view model =
div []
[ map Top (Counter.view model.topCounter)
, map Bottom (Counter.view model.bottomCounter)
, button [ onClick Reset ] [ text "RESET" ]
]These changes are nice for a couple really good reasons:
- Addresses were consistently one of the things that new folks found most confusing.
- It allows the
elm-lang/virtual-domimplementation to be more efficient withlazy - It uses a normal
mapinstead of some unfamiliar API.
You can see more examples of the new HTML API here.
`Effects` is now `Cmd`
If you are working with HTTP or anything, you are probably using evancz/elm-effects and have your update function returning Effects values. That library was a successful experiment, so it has been folded into elm-lang/core and given a name that works better in the context of Elm 0.17.
The changes are basically a simple rename:
-- 0.16
update : Action -> Model -> (Model, Effects Action)
update action model =
case action of
RequestMore ->
(model, getRandomGif model.topic)
NewGif maybeUrl ->
( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl)
, Effects.none
)
-- 0.17
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
RequestMore ->
( model, getRandomGif model.topic )
NewGif maybeUrl ->
( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl)
, Cmd.none
)The Cmd stuff lives in elm-lang/core in Platform.Cmd. It is imported by default with import Platform.Cmd as Cmd exposing (Cmd) to make it easier to use.
Again, very easy changes. The key goal of 0.17 was to manage effects in a nicer way, so in making these facilities more complete, the term Effects became very ambiguous. You should read more about this in the updated Elm Architecture Tutorial which has a section all about effects.
`StartApp` is now `Html.App`
The evancz/start-app package was an experiment to help people get productive with Elm more quickly. It meant that newcomers could get really far with Elm without knowing a ton about signals, and it has been very effective. With 0.17, it has been folded in to elm-lang/html in the Html.App module.
Upgrading looks like this:
-- 0.16 ---------------------------------------
import StartApp
import Task
app =
StartApp.start
{ init = init, update = update, view = view, inputs = [] }
main =
app.html
port tasks : Signal (Task.Task Never ())
port tasks =
app.tasks
-- 0.17 ---------------------------------------
import Html.App as Html
main =
Html.program
{ init = init, update = update, view = view, subscriptions = \_ -> Sub.none }The type of main has changed from Signal Html to Program flags. The main value is a program that knows exactly how it needs to be set up. All that will be handled by Elm, so you no longer need to specially hook tasks up to a port or anything.
Upgrading Ports
Talking to JavaScript still uses ports. It is pretty similar, but adapted to fit nicely with commands and subscriptions.
Here is the change for outgoing ports:
-- 0.16
port focus : Signal String
port focus =
...
-- 0.17
port focus : String -> Cmd msgInstead of hooking up a signal, you have a function that can create commands. So you just call focus : String -> Cmd msg from anywhere in your app and the command is processed like all the others.
And here is the change for incoming ports:
type User = { name : String, age : Int }
-- 0.16
port users : Signal User
-- 0.17
port users : (User -> msg) -> Sub msgInstead of getting a signal to route to the right place, we now can create subscriptions to incoming ports. So wherever you need to know about users, you just subscribe to it.
You should definitely read more about this here.
JavaScript Interop
The style of initializing Elm programs in JS has also changed slightly.
| Initialize | 0.16 | 0.17 |
|---|---|---|
| Embed | Elm.embed(Elm.Main, someNode); | Elm.Main.embed(someNode); |
| Fullscreen | Elm.fullscreen(Elm.Main); | Elm.Main.fullscreen(); |
| Worker | Elm.worker(Elm.Main); | Elm.Main.worker(); |
Next Steps
From here, I would highly recommend looking through guide.elm-lang.org, particularly the sections on The Elm Architecture. This will help you get a feel for 0.17.
Upgrade Instructions/0.18
Upgrading to 0.18
Like always, not that much has really changed. To make the process as smooth as possible, this document outlines all the things you will want to do to use 0.18.
- Update
elm-package.json - List Ranges
- No More Primes
- Backticks and
andThen - Renamed Functions in Core
- Package Changes
A lot of this can be done automatically with elm-upgrade, so check it out after reading through this document!
Update elm-package.json
So the first thing you want to do is update your elm-package.json file. The only tricky thing is that the HTTP package moved:
evancz/elm-http=>elm-lang/http
From there, here is an elm-package.json that has been properly updated:
{
"version": "1.0.0",
"summary": "let people do a cool thing in a fun way",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"src"
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0",
"elm-lang/http": "1.0.0 <= v < 2.0.0",
"evancz/elm-markdown": "3.0.1 <= v < 4.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}The only changes should be in the dependencies and elm-version fields where you need to update constraints.
The easiest way to get this all set up is to use elm-upgrade, but you can also:
- Update
elm-versionby hand. - Remove everything from
dependenciesby hand. - Install what you need with
elm-package install elm-lang/coreone-by-one.
List Ranges
The [1..5] syntax has been removed.
So replace any occurance of [1..9] with List.range 1 9.
No More Primes
You are not allowed to have primes in variable names, so things like type' are renamed to type_.
Backticks and `andThen`
Elm used to let you take normal functions and use them as infix operators. This is most notable in the case of andThen which is pretty much the only function that used this feature. You will want to make the following updates to your code:
-- old
andThenIn17 : Result String Int
andThenIn17 =
String.toInt "1234"
`Result.andThen` \year -> isValidYear year
-- andThen : Result x a -> (a -> Result x b) -> Result x b
-- new
andThenIn18 : Result String Int
andThenIn18 =
String.toInt "1234"
|> Result.andThen (\year -> isValidYear year)
-- andThen : (a -> Result x b) -> Result x a -> Result x bNotice that the backtick style is replaced by pipelining. The onError function has been flipped in the same way, so if you are working with tasks you may say something like this in 0.18:
type Msg = NewText String | DidNotLoad
tasksIn18 : Task x Msg
tasksIn18 =
Http.toTask (Http.getString "http://example.com/war-and-peace")
|> Task.andThen (\fullText -> Task.succeed (NewText fullText))
|> Task.onError (\error -> Task.succeed DidNotLoad)This also means that andThen and onError group together much better than in the infix style.
This change should be happening across the entire Elm ecosystem as package authors upgrade to 0.18.
Renamed Functions in Core
A couple functions have been removed or renamed.
-
objectNbecomesmapN(Note:object1becomesmap)tupleNbecomesmapNwithindex(:=)becomesfieldandThenargs flip
-
shiftLeftbecomesshiftLeftByand args flipshiftRightbecomesshiftRightByand args flipshiftRightLogicalbecomesshiftRightZfByand args flip
-
andThenargs fliponErrorargs flip- Removed
perform : (x -> msg) -> (a -> msg) -> Task x a -> Cmd msg - Added
perform : (a -> msg) -> Task Never a -> Cmd msg - Added
attempt : (Result x a -> msg) -> Task x a -> Cmd msg - Removed
toMaybeandtoResultin favor of usingonErrordirectly
-
- Renamed
formatErrortomapErrorto match names inTask andThenargs flip
- Renamed
-
andThenargs flip- Removed
oneOf
-
andThenargs flip
-
Basics.fstbecomesTuple.firstBasics.sndbecomesTuple.second
Package Changes
The following packages have changed a little bit:
elm-lang/htmlcollapsedHtml.AppintoHtml. So you need to remove anyimport Html.Appimports and refer toHtml.programinstead.elm-lang/httpwas redone to be easier and have more features. It now supports tracking progress and rate-limiting HTTP requests. It should be pretty easy to upgrade to the new stuff, but if you have a complexTaskthat chains many requests, you will want to use theHttp.toTaskfunction to keep that code working the same.elm-lang/navigationno longer has its own concept of aParser. You just turn aNavigation.Locationinto a message and it is fed into your normalupdatefunction. This meansNavigation.programis now much closer toHtml.programso this should simplify things a bit.evancz/url-parseris pretty much the same, but works better and is friendlier. New things include:- You can use
<?>to parse query parameters. - Some bugs about parsing leading and trailing slashes are fixed.
- The parser backtracks, always finding a valid parse of the URL if one exists.
- You can use
parsePathto parse aNavigation.Locationdirectly.
- You can use
In all cases, the packages have become simpler and easier to use. The actual changes did not seem to be too serious as I upgraded elm-lang.org and package.elm-lang.org and all the examples I control.
Upgrade Instructions/0.19.0
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 diff`elm.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 451(,)becomesTuple.pairstyle : 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.
Upgrade Instructions/0.19.1
Upgrading to 0.19.1
There are no language changes, so once you swap to "elm-version": "0.19.1" in your elm.json, most users should be able to proceed without any further code changes. You may run into a handful of bugfixes though! These cases are outlined below!
Improvements
- Parse error message quality (like this and this)
- Faster compilation, especially for incremental compiles
- Uses filelocks so that cached files are not corrupted when plugins run
elm makemultiple times on the same project at the same time. (Still worth avoiding that though!) - More intuitive multiline declarations in REPL
- Various bug fixes (e.g.
--debug,x /= 0,type Height = Height Floatin--optimize)
Detectable Bug Fixes
There are three known cases where code that compiled with 0.19.0 will not compile with 0.19.1 due to bug fixes:
1. Ambiguous Imports
Say you have an import like this:
import Html exposing (min)
import Regex exposing (never)
x = min
y = neverThese should be reported as ambiguous usages since the names are also exposed by Basics, but there was a regression in 0.19.0 described here such that they weren't caught in specific circumstances.
The fix is to use a qualified name like Html.min or Regex.never to make it unambiguous.
We found a couple instances of this in packages and have submitted PRs to the relevant authors in August 2019. You may run into this in your own code as well.
For more details on why this is considered a regression, check out the details here or try it in 0.18.0 to see how it worked before.
2. Tabs in Comments
The 0.19.0 binaries did not catch tab characters in comments. The new parser is better at checking for tabs, so it will object when it finds these.
Again, we found this in some packages and reached out to the relevant authors with PRs so patches would be published before the 0.19.1 release.
3. Port Module with no Ports
If you have any files that start with:
port module Main exposing (..)But they do not actually have any port declarations, the 0.19.1 binary will ask you to switch to a normal module declaration like module Main exposing (..)
Upgrade Instructions/Earlier
0.16
Read all about it at these links:
- http://elm-lang.org/blog/compilers-as-assistants
- https://github.com/elm-lang/elm-platform/blob/master/upgrade-docs/0.16.md
0.15
Improve Import Syntax
The changes in 0.14 meant that people were seeing pretty long import sections,
sometimes with two lines for a single module to bring it in qualified and to
expose some unqualified values. The new syntax is like this:
import List
-- Just bring `List` into scope, allowing you to say `List.map`,
-- `List.filter`, etc.
import List exposing (map, filter)
-- Bring `List` into scope, but also bring in `map` and `filter`
-- without any prefix.
import List exposing (..)
-- Bring `List` into scope, and bring in all the values in the
-- module without a prefix.
import List as L
-- Bring `L` into scope, but not `List`. This lets you say `L.map`,
-- `L.filter`, etc.
import List as L exposing (map, filter)
-- Bring `L` into scope along with unqualified versions of `map`
-- and `filter`.
import List as L exposing (..)
-- Bring in all the values unqualified and qualified with `L`.This means you are doing more with each import, writing less overall. It also
makes the default imports more comprehensive because you now can refer toList and Result without importing them explicitly as they are in the
defaults.
Revise Port Syntax
One common confusion with the port syntax is that the only difference
between incoming ports and outgoing ports is whether the type annotation comes
with a definition. To make things a bit clearer, we are using the keywordsforeign input and foreign output.
foreign input dbResults : Stream String
foreign output dbRequests : Stream String
foreign output dbRequests =
Stream.map toRequest userNamesInput / Output
The biggest change in 0.15 is the addition of tasks, allowing us to represent
arbitrary effects in Elm in a safe way. This parallels how ports work, so we
are trying to draw attention to that in syntax. First addition is a way to
create new inputs to an Elm program.
input actions : Input ActionThis creates a Input that is made up of an Address you can send messages to
and a Stream of those messages. This is similar to a foreign input except
there we use the name as the address. The second addition is a way to run
tasks.
output Stream.map toRequest userNamesThis lets us turn tasks into effects in the world. Sometimes it is useful to
pipe the results of these tasks back into Elm. For that, we have the third and
final addition.
input results : Stream (Result Http.Error String)
input results from
Stream.map toRequest userNames0.14.1
Modify default import of List to expose (::) as well.
0.14
Breaking Changes
- Keyword
datarenamed totype - Keyword
typerenamed totype alias
0.13
Improvements:
- Type aliases in port types
- Add Keyboard.alt and Keyboard.meta
- Add Debug.crash, Debug.watch, Debug.watchSummary, and Debug.trace
- Add List.indexedMap and List.filterMap
- Add Maybe.map
- Add Basics.negate
- Add (>>) to Basics as in F#
- Add --bundle-runtime flag which creates stand-alone Elm programs
- Error on ambiguious use of imported variables
- Replace dependency on Pandoc with cheapskate+kate
- Better architecture for compiler. Uses types to make compilation pipeline
safer, setting things up for giving programmatic access to the AST to
improve editor and IDE support.
Breaking Changes:
- Rename (.) to (<<) as in F#
- Rename Basics.id to Basics.identity
- Rename Basics.div to (//)
- Rename Basics.mod to (%)
- Remove Maybe.justs for (List.filterMap identity)
- Remove List.and for (List.foldl (&&) True)
- Remove List.or for (List.foldl (||) False)
- Unambiguous syntax for importing ADTs and type aliases
- sqrt and logBase both only work on Floats now
0.12.3
- Minor changes to support webgl as a separate library
- Switch from HSV to HSL
- Programmatic access to colors with toHsl and toRgb
0.12.1
Improvements:
- New Array library (thanks entirely to @Xashili)
- Json.Value can flow through ports
- Improve speed and stack usage in List library (thanks to @maxsnew)
- Add Dict.filter and Dict.partition (thanks to @hdgarrood)
Breaking Changes:
- Revamp Json library, simpler with better names
- Revamp JavaScript.Experimental library to have slightly better names
- Remove JavaScript library which was made redundant by ports
0.12
Breaking Changes:
- Overhaul Graphics.Input library (inspired by Spiros Eliopoulos and Jeff Smitts)
- Overhaul Text library to accomodate new Graphics.Input.Field
library and make the API more consistent overall - Overhaul Regex library (inspired by Attila Gazso)
- Change syntax for "import open List" to "import List (..)"
- Improved JSON format for types generated by elm-doc
- Remove problematic Mouse.isClicked signal
- Revise the semantics of keepWhen and dropWhen to only update when
the filtered signal changes (thanks Max New and Janis Voigtlรคnder)
Improvements:
- Add Graphics.Input.Field for customizable text fields
- Add Trampoline library (thanks to @maxsnew and @timthelion)
- Add Debug library (inspired by @timthelion)
- Drastically improved performance on markdown parsing (thanks to @Dandandan)
- Add Date.fromTime function
- Use pointer-events to detect hovers on layered elements (thanks to @Xashili)
- Fix bugs in Bitwise library
- Fix bug when exporting Maybe values through ports
0.11
- Ports, a new FFI that is more general and much nicer to use
- Basic compiler tests (thanks to Max New)
0.10.1
- sort, sortBy, sortWith (thanks to Max Goldstein)
- elm-repl
- Bitwise library
- Regex library
- Improve Transform2D library (thanks to Michael Sรธndergaard)
0.10
- Native strings
- Tango colors
- custom precedence and associativity for infix operators
- elm-doc released with new documentation format
- Realiasing in type errors
- Rename Matrix2D => Transform2D
- Add Random.floatList (thank you Max GoldStein)
- Fix remove function in Dict (thank you Max New)
- Start using language-ecmascript for JS generation
- Make compatable with cabal-1.18 (thank you Justin Leitgeb)
- All functions with 10+ arguments (thanks to Max New)
0.9.1
- Allow custom precedence and associativity for user-defined infix ops
- Realias types before printing
- Switch to Tango color scheme, adding a bunch of nice colors
- add the greyscale function for easily producing greys
- Check the type of main
- Fix miscellaneous bugs in type checker
- Switch name of Matrix2D to Transform2D
0.9
Build Improvements:
- Major speed improvements to type-checker
- Type-checker should catch all type errors now
- Module-level compilation, only re-compile if necessary
- Import types and type aliases between modules
- Intermediate files are generated to avoid unneeded recompilation
and shorten compile time. These files go in ElmFiles/ by default - Generated files are placed in ElmFiles/ by default, replicating
the directory structure of your source code.
Error Messages:
- Cross-module type errors
- Errors for undefined values
- Pretty printing of expressions and types
Syntax:
- Pattern matching on literals
- Pattern aliases with
as(Andrew) - Unary negation
- Triple-quoted multi-line strings
- Type annotations in let expressions (Andrew)
- Record Constructors
- Record type aliases can be closed on the zeroth column
- (,,) syntax in types
- Allow infix op definitions without args: (*) = add
- Unparenthesized if, let, case, lambda at end of binary expressions
elm-server:
- Build multi-module projects
- Report all errors in browser
Libraries:
- Detect hovering over any Element
- Set alpha of arbitrary forms in collages
- Switch Text.height to use px instead of em
Bug Fixes:
- Many bug fixes for collage, especially when rendering Elements.
Website:
- Hot-swapping
- Much faster page load with pre-compiled Elm files (Max New)
forgot to fill this in again...
0.7.2
- Add a WebSockets library.
- Add support for the mathematical looking operator for function composition (U+2218).
forgot to fill this in for a while...
0.5.0
Add Dict, Set, and Automaton libraries!
Add (,,) notation for creating tuples.
Redo HTTP library, allowing any kind of request and more flexibility.
Remove the library prefixes
Data.,Graphics., andSignal.because
they were more confusing than helpful.Better type error reporting for ambiguous uses of variables and for
variables in aliased modules.Add
readIntandreadFloatfunctions.Add
complementfunction to compute complementary colors.Ensure that
Stringis treated as an alias of[Char].Fix bug in pattern parsing.
A B _ _was parsed asA (B _ _).Make pattern matching a bit more compact in generated code.
Make generated JS more readable.
The Haskell API exports the absolute path to the Elm runtime
system (with the corresponding version number). This makes it easier
to run Elm programs with less setup.
0.4.0
This version is all about graphics: nicer API with more features and major
efficiency improvements. I am really excited about this release!
Add native Markdown support. You can now embed markdown directly in .elm files
and it is used as anElement. Syntax is[markdown| ... |]where...is
formatted as described here.
Content can span multiple lines too.Drastically improve the
collageinterface. You can now move, rotate, and scale
the following forms:- Elements (any Element you want can be turned into a Form with
toForm) - Images
- Shapes (shapes can be textured now too)
- Lines
This will make it way easier to make games in Elm. Games can now include text,
gifs, videos, and any other Element you can think of.
- Elements (any Element you want can be turned into a Form with
Add
--minifyflag, to minify JS code.Significantly improve performance of pattern matching.
Compiler performs beta-reduction in some simple cases.
The rendering section of the Elm runtume-system (RTS) has been totally rewritten,
making screen refreshes use fewer cycles, less memory, and cause less garbage-collection.
0.3.6
Add JSON library.
Type-error messages improved. Gives better context for error, making them
easier to find. Better messages for runtime errors as well (errors that
the type checker cannot find yet).Add Comparable super-type which allows the comparision of any values
of type {Int,Float,Char,String}. Now possible to make Set and Map libraries.Parser now handles decimal numbers.
Added many new functions for manipulating numbers:
- truncate, round, floor, ceiling :: Float -> Int
- toFloat :: Int -> Float
- (^) :: Number -> Number -> Number
- e :: Float
Foreign import/export statements no longer have to preceed all other
variable and datatype definitions. They can be mixed in, making things
a bit more readable/natural.Bug fixes:
- The
toTextfunction did not escape strings properly - Correct
castJSTupleToTupleNfamily of functions foldr1took the leftmost element as the base case instead of the rightmost- Fix minor display issue in latest version of Chrome.
- Fix behavior of [ lo .. hi ] syntax (now [4..0] == [], not [0]).
- The
0.3.5
Add JavaScript event interface. Allows Elm to import and export JS values
and events. This makes it possible to import and export Elements, so users
can use JS techniques and libraries if necessary. Conversion between JS
and Elm values happens with functions from here:
http://localhost:8000/docs/Foreign/JavaScript.elm
http://localhost:8000/docs/Foreign/JavaScript/Experimental.elmAdd new flags to help with JavaScript event interface.
Add three built-in event listeners (elm_title, elm_log, elm_redirect) that
make it possible to make some common/simple imperative actions without
having to worry about writing the JS yourself. For example:
foreign export jsevent "elm_title"
title :: Signal JSString
will update the page's title to the current value of the title signal.
Empty strings are ignored. "elm_redirect" and "elm_log" events work much
the same way, except that "elm_log" does not skip empty strings.Add new Signal functions:
count :: Signal a -> Signal Int
keepIf :: (a -> Bool) -> a -> Signal a -> Signal a
dropIf :: (a -> Bool) -> a -> Signal a -> Signal a
keepWhen :: Signal Bool -> a -> Signal a -> Signal a
dropWhen :: Signal Bool -> a -> Signal a -> Signal a
dropRepeats :: Signal a -> Signal a
sampleOn :: Signal a -> Signal b -> Signal b
clicks :: Signal ()
The keep and drop functions make it possible to filter events, which
was not possible in prior releases. More documentation:
http://elm-lang.org/docs/Signal/Signal.elmAdd examples of JS event interface and new signal functions:
https://github.com/evancz/Elm/tree/master/Examples/elm-jsUse more compressed format for strings. Should make strings 10-12 times
more space efficient than in previous releases. Anecdotal evidence:
Elm's home page is now 70% of its previous size.Add new function to Data.List:
last :: [a] -> aFix parenthesization bug with binary operators.
0.3.0
Major Changes (Read this part!)
- Add a basic module system.
- Elm's JavaScript runtime is now distributed with the elm package.
Previously it was available for download as an unversioned JavaScript
file (elm-mini.js). It is now installed with the elm compiler as
elm-runtime-0.3.0.js. Be sure to serve the Elm runtime system that matches
the version of the compiler used to generate JavaScript. When working
locally, the compiler will automatically use your local copy of this file. - BREAKING CHANGE: rgb and rgba (in the color module) now take their red,
green, and blue components as integers between 0 and 255 inclusive. - Improve error messages for parse errors and runtime errors.
New Functions and Other Additions
- Add support for keyboard events: Keyboard.Raw
- Add buttons in Signal.Input:
button :: String -> (Element, Signal Bool) - Add new basic element (an empty rectangle, good for adding spaces):
rectangle :: Int -> Int -> Element - Add (an awkwardly named) way to display right justified text: rightedText
- Add two basic libraries: Data.Char and Data.Maybe
- Add some new colors: magenta, yellow, cyan, gray, grey
- Add functions to Data.List module: take, drop
- Add functions to Prelude (the default imports):
fst, snd, curry, uncurry, and a bunch of list functions - Add --make, --separate-js, and --only-js flags to help compile
with the new module system.
Elm.Json/Application
`elm.json` for applications
This is a decent baseline for pretty much any applications made with Elm. You will need these dependencies or more.
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.2",
"dependencies": {
"direct": {
"elm/browser": "1.0.0",
"elm/core": "1.0.0",
"elm/html": "1.0.0",
"elm/json": "1.0.0"
},
"indirect": {
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.0"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}`"type"`
Either "application" or "package". All the other fields are based on this choice!
`"source-directories"`
A list of directories where Elm code lives. Most projects just use "src" for everything.
`"elm-version"`
The exact version of Elm this builds with. Should be "0.19.2" for most people!
`"dependencies"`
All the packages you depend upon. We use exact versions, so your elm.json file doubles as a "lock file" that ensures reliable builds.
You can use modules from any "direct" dependency in your code. Some "direct" dependencies have their own dependencies that folks typically do not care about. These are the "indirect" dependencies. They are listed explicitly so that (1) builds are reproducible and (2) you can easily review the quantity and quality of dependencies.
Note: We plan to eventually have a screen in reactor that helps add, remove, and upgrade packages. It can sometimes be tricky to keep all of the constraints happy, so we think having a UI will help a lot. If you get into trouble in the meantime, adding things back one-by-one often helps, and I hope you do not get into trouble!
`"test-dependencies"`
All the packages that you use in tests/ with elm-test but not in the application you actually want to ship. This also uses exact versions to make tests more reliable.
Elm.Json/Package
`elm.json` for packages
This is roughly elm.json for the elm/json package:
{
"type": "package",
"name": "elm/json",
"summary": "Encode and decode JSON values",
"license": "BSD-3-Clause",
"version": "1.0.0",
"exposed-modules": [
"Json.Decode",
"Json.Encode"
],
"elm-version": "0.19.0 <= v < 0.20.0",
"dependencies": {
"elm/core": "1.0.0 <= v < 2.0.0"
},
"test-dependencies": {}
}`"type"`
Either "application" or "package". All the other fields are based on this choice.
`"name"`
The name of a GitHub repo like "elm-lang/core" or "rtfeldman/elm-css".
Note: We currently only support GitHub repos to ensure that there are no author name collisions. This seems like a pretty tricky problem to solve in a pleasant way. For example, do we have to keep an author name registry and give them out as we see them? But if someone is the same person on two platforms? And how to make this all happen in a way this is really nice for typical Elm users? Etc. So adding other hosting endpoints is harder than it sounds.
`"summary"`
A short summary that will appear on package.elm-lang.org that describes what the package is for. Must be under 80 characters.
`"license"`
An OSI approved SPDX code like "BSD-3-Clause" or "MIT". These are the two most common licenses in the Elm ecosystem, and BSD-3-Clause is a good default. But you can see the full list of options here.
`"version"`
All packages start at "1.0.0" and from there, Elm automatically enforces semantic versioning by comparing API changes.
So if you make a PATCH change and call elm bump it will update you to "1.0.1". And if you then decide to remove a function (a MAJOR change) and call elm bump it will update you to "2.0.0". Etc.
`"exposed-modules"`
A list of modules that will be exposed to people using your package. The order you list them will be the order they appear on package.elm-lang.org.
Note: If you have five or more modules, you can use a labelled list like this. We show the labels on the package website to help people sort through larger packages with distinct categories. Labels must be under 20 characters.
`"elm-version"`
The range of Elm compilers that work with your package. Right now "0.19.0 <= v < 0.20.0" is always what you want for this.
`"dependencies"`
A list of packages that you depend upon. In each application, there can only be one version of each package, so wide ranges are great. Fewer dependencies is even better though!
Note: Dependency ranges should only express tested ranges. It is not nice to use optimistic ranges and end up causing build failures for your users down the line. Eventually we would like to have an automated system that tries to build and test packages as new packages come out. If it all works, we could send a PR to the author widening the range.
`"test-dependencies"`
Dependencies that are only used in the tests/ directory by elm test. Values from these packages will not appear in any final build artifacts.
README
Elm
A delightful language for reliable webapps.
Check out the Home Page, Try Online, or The Official Guide
Install
โจ Install โจ
For multiple versions, previous versions, and uninstallation, see the instructions here.
Help
If you are stuck, ask around on the Elm slack channel. Folks are friendly and happy to help with questions!