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:
<table>
<tr>
<th>feature</th>
<th>0.15.1</th>
<th>0.16</th>
</tr>
<tr>
<td>field update</td>
<td><pre lang="elm">{ record | x <- 42 }</pre></td>
<td><pre lang="elm">{ record | x = 42 }</pre></td>
</tr>
<tr>
<td>field addition</td>
<td><pre lang="elm">{ record | x = 42 }</pre></td>
<td>removed</td>
</tr>
<tr>
<td>field deletion</td>
<td><pre lang="elm">{ record - x }</pre></td>
<td>removed</td>
</tr>
<tr>
<td>record constructors that add fields</td>
<td>
<pre lang="elm">
type alias Named r =
{ r | name : String }
-- generates a function like this:
-- Named : String -> r -> Named r
</pre>
</td>
<td>
<pre lang="elm">
type alias Named r =
{ r | name : String }
</pre>
Generates no function. Field addition is gone. A function
will still be generated for "closed" records though.
</td>
</tr>
<tr>
<td>field parameters</td>
<td>
<pre lang="elm">
type alias Foo =
{ prefix : String -> String }
foo : Foo
foo = { prefix x = "prefix" ++ x }
</pre>
</td>
<td>
<pre lang="elm">
type alias Foo =
{ prefix : String -> String }
foo : Foo
foo = { prefix = \x-> "prefix" ++ x }
</td>
</tr>
<tr>
<td>multi-way if</td>
<td>
<pre lang="elm">
if | x < 0 -> "left"
| x > 0 -> "right"
| otherwise -> "neither"
</pre>
</td>
<td>
<pre lang="elm">
if x < 0 then
"left"
else if x > 0 then
"right"
else
"neither"
</pre>
</td>
</tr>
</table>
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:
1. A union type that models things with a simpler API, like in this case.
2. 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.otherwise
* Signal.(<~)
* 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-html is now elm-lang/html
- evancz/elm-svg is now elm-lang/svg
- evancz/virtual-dom is now elm-lang/virtual-dom
- The functionality of evancz/start-app now lives in elm-lang/html in Html.App
- The functionality of evancz/elm-effects now lives in elm-lang/core in Platform.*
- The functionality of Graphics.* now lives in evancz/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:
<table>
<tr>
<th>feature</th>
<th>0.16</th>
<th>0.17</th>
</tr>
<tr>
<td>module declaration</td>
<td><pre lang="elm">module Queue (..) where</pre></td>
<td><pre lang="elm">module Queue exposing (..)</pre></td>
</tr>
</table>
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 | Decrement
The 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-dom implementation to be more efficient with lazy
- It uses a normal map instead 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 Taskapp =
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 msg
Instead 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 msg
Instead 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.
<table>
<tr>
<th>Initialize</th>
<th>0.16</th>
<th>0.17</th>
</tr>
<tr>
<td>Embed</td>
<td><pre lang="javascript">Elm.embed(Elm.Main, someNode);</pre></td>
<td><pre lang="javascript">Elm.Main.embed(someNode);</pre></td>
</tr>
<tr>
<td>Fullscreen</td>
<td><pre lang="javascript">Elm.fullscreen(Elm.Main);</pre></td>
<td><pre lang="javascript">Elm.Main.fullscreen();</pre></td>
</tr>
<tr>
<td>Worker</td>
<td><pre lang="javascript">Elm.worker(Elm.Main);</pre></td>
<td><pre lang="javascript">Elm.Main.worker();</pre></td>
</tr>
</table>
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-version by hand.
- Remove everything from dependencies by hand.
- Install what you need with elm-package install elm-lang/core one-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:
-- oldandThenIn17 : 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 b
Notice 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 | DidNotLoadtasksIn18 : 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.
- Json.Decode
- objectN becomes mapN (Note: object1 becomes map)
- tupleN becomes mapN with index
- (:=) becomes field
- andThen args flip
- Bitwise
- shiftLeft becomes shiftLeftBy and args flip
- shiftRight becomes shiftRightBy and args flip
- shiftRightLogical becomes shiftRightZfBy and args flip
- Task
- andThen args flip
- onError args 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 toMaybe and toResult in favor of using onError directly
- Result
- Renamed formatError to mapError to match names in Task
- andThen args flip
- Maybe
- andThen args flip
- Removed oneOf
- Random
- andThen args flip
- Tuple
- Basics.fst becomes Tuple.first
- Basics.snd becomes Tuple.second
Package Changes
The following packages have changed a little bit:
- elm-lang/html collapsed Html.App into Html. So you need to remove any import Html.App imports and refer to Html.program instead.
- elm-lang/http was 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 complex Task that chains many requests, you will want to use the Http.toTask function to keep that code working the same.
- elm-lang/navigation no longer has its own concept of a Parser. You just turn a Navigation.Location into a message and it is fed into your normal update function. This means Navigation.program is now much closer to Html.program so this should simplify things a bit.
- evancz/url-parser is 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 parsePath to parse a Navigation.Location directly.
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-upgrade which 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.<br>
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
<br>
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.json for applications
- elm.json for packages
Both are quite similar to the elm-package.json format, and elm-upgrade can help you with this.
<br>
Changes
#### Functions Changed
- String.toInt : String -> Maybe Int (not Result anymore)
- String.toFloat : String -> Maybe Float (not Result anymore)
- Basics.toString becomes Debug.toString, String.fromInt, and String.fromFloat.
- Basics.rem 451 10 becomes remainderBy 10 451
- 451 % 10 becomes modBy 10 451
- (,) becomes Tuple.pair
- style : List (String, String) -> Attribute msg becomes String -> String -> Attribute msg
- Html.beginnerProgram becomes Browser.sandbox.
- Html.program becomes Browser.element and Browser.document.
#### Modules Moved
- Json.Encode and Json.Decode moved to elm/json
- Time and Date moved to elm/time with a significantly improved API
- Random moved to elm/random with a better implementation and a few new functions
- Regex moved to elm/regex with a much clearer README
#### Packages Moved
- elm-lang/ moved to elm/
- evancz/url-parser moved to elm/url with a simpler and more flexible API
- elm-tools/elm-parser moved to elm/parser with speed boost when compiling with the --optimize flag
- elm/browser combines and simplifies the following 0.18 packages:
- elm-lang/navigation with smoother APIs
- elm-lang/dom with ability to get node positions and dimensions.
- elm-lang/mouse with decoders
- elm-lang/window
- elm-lang/keyboard uses decoders like this
- elm-lang/page-visibility
- elm-lang/animation-frame
#### Functions Removed
- uncurry
- curry
- flip
- (!)
Prefer named helper functions in these cases.
<br>
--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 Float to just be a float at runtime
- Unbox Char values
- Use more compact names for type constructors 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.
<br>
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 than O(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!
<br>
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!
<br>
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.
<br>
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.
<br>
Notes:
- toString — A relatively common bug was to show an Int in the UI, and then later that value changes to something else. toString would just show wrong information until someone noticed. The new String.fromInt and String.fromFloat ensure 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!
<br>
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 make multiple 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 Float in --optimize)
<br>
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 = never
These 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 Stringforeign output dbRequests : Stream String
foreign output dbRequests =
Stream.map toRequest userNames
Input / 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 data renamed to type
* Keyword type renamed to type 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., and Signal. because
they were more confusing than helpful.
* Better type error reporting for ambiguous uses of variables and for
variables in aliased modules.
* Add readInt and readFloat functions.
* Add complement function to compute complementary colors.
* Ensure that String is treated as an alias of [Char].
* Fix bug in pattern parsing. A B _ _ was parsed as A (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 an Element. Syntax is [markdown| ... |] where ... is
formatted as described here.
Content can span multiple lines too.
* Drastically improve the collage interface. 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.
* Add --minify flag, 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 toText function did not escape strings properly
- Correct castJSTupleToTupleN family of functions
- foldr1 took 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]).
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.elm
* Add 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.elm
* Add examples of JS event interface and new signal functions:
https://github.com/evancz/Elm/tree/master/Examples/elm-js
* Use 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] -> a
* Fix 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": {}
}
}<br>
"type"
Either "application" or "package". All the other fields are based on this choice!
<br>
"source-directories"
A list of directories where Elm code lives. Most projects just use "src" for everything.
<br>
"elm-version"
The exact version of Elm this builds with. Should be "0.19.2" for most people!
<br>
"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!
<br>
"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": {}
}<br>
"type"
Either "application" or "package". All the other fields are based on this choice.
<br>
"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.
<br>
"summary"
A short summary that will appear on package.elm-lang.org that describes what the package is for. Must be under 80 characters.
<br>
"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.
<br>
"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.
<br>
"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.
<br>
"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.
<br>
"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.
<br>
"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
<br>
Install
✨ Install ✨
For multiple versions, previous versions, and uninstallation, see the instructions here.
<br>
Help
If you are stuck, ask around on [the Elm slack channel][slack]. Folks are friendly and happy to help with questions!
[slack]: https://elm-lang.org/community/slack
---